Injection Rules¶
The dependency injection mechanism relies heavily on template metaprogramming and it has some limitations.
General¶
Only one constructor should be defined for each instance implementation
If the service is registered with interface and implementation, the interface should have a virtual destructor
If multiple services are registered by the same interface, all should have the same lifetime (the build method will throw an exception)
Only one service implementation can be registered (the build method will throw an exception)
Injecting Services¶
- Singleton/scoped services can be injected using one of:
References: (T&)
Pointers: (T*)
- Transient services can be injected using one of:
std::unique_ptr: (unique_ptr<T>)
In-place object if type is movable or copyable: T
- Multiple services implementing the same interface can be injected using std::vector:
Transient (std::vector<std::unique_ptr<T>>)
Singleton/scoped (std::vector<T*>)
Constructor param type |
ServiceProvider method used |
|---|---|
T - if movable or copyable |
provider.createServiceInPlace<T>() |
std::unique_ptr<T> |
provider.createService<T>() |
T& |
provider.getService<T>() |
T* |
provider.tryGetService<T>() |
std::vector<T*> |
provider.getServices<T>() |
std::vector<std::unique_ptr<T>> |
provider.createServices<T>() |
#include <SevenBit/DI.hpp>
#include <cassert>
#include <memory>
using namespace sb::di;
struct NotReqisteredService
{
};
struct SingletonService
{
};
struct ScopedService
{
};
struct TransientService
{
};
class ServiceExecutor
{
public:
ServiceExecutor(NotReqisteredService *notRegistered, SingletonService &singleton, ScopedService *scoped,
std::unique_ptr<TransientService> transient, TransientService transientInPlace,
std::vector<ScopedService *> scopedList,
std::vector<std::unique_ptr<TransientService>> trasientList)
{
assert(notRegistered == nullptr);
assert(scoped != nullptr);
assert(transient != nullptr);
assert(scopedList.size() == 1);
assert(trasientList.size() == 1);
}
};
int main()
{
ServiceProvider provider = ServiceCollection{}
.addSingleton<SingletonService>()
.addScoped<ScopedService>()
.addTransient<TransientService>()
.addScoped<ServiceExecutor>()
.buildServiceProvider();
auto &consumer = provider.getService<ServiceExecutor>();
return 0;
}