Injection Rules#

The dependency injection mechanism relies heavily on template metaprogramming and it has some limitations. The most important one is that we cannot inject service into service using reference.

General#

  • Only one constructor should be defined for each service 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)

  • It is guaranteed that injected service won’t be null

Injecting Services#

  • Services cannot be injected by value: (T)

  • Singleton/scoped services can be injected using one of:

    • Pointers: (T*)

    • Const pointner: (T* const)

    • Pointner to const object: (const T*)

    • Const pointer to const object: (const T* const)

  • Transient services can be injected using std::unique_ptr: (unique_ptr<T>)

  • Multiple services implementing specified interface can be injected using std::vector:

    • Transient (std::vector<std::unique_ptr<T>>)

    • Singleton/scoped (std::vector<T*>)

Examples/Guides/InjectionRules#
#include <SevenBit/DI.hpp>
#include <iostream>
#include <memory>

using namespace sb::di;

struct SingletonService
{
};
struct ScopedService
{
};
struct TransientService
{
};

class ServiceExecutor
{
  public:
    ServiceExecutor(const SingletonService *singleton, std::vector<ScopedService *> scoped,
                    std::vector<std::unique_ptr<TransientService>> trasients)
    {
    }
};
int main()
{
    IServiceProvider::Ptr provider = ServiceCollection{}
                                         .addSingleton<SingletonService>()
                                         .addScoped<ScopedService>()
                                         .addTransient<TransientService>()
                                         .addScoped<ServiceExecutor>()
                                         .buildServiceProvider();

    ServiceExecutor &consumer = provider->getService<ServiceExecutor>();

    return 0;
}