Services LifeTime#

Service providers can create scoped service providers:

IServiceProvider::Ptr provider = ServiceCollection{}.buildServiceProvider();

IServiceProvider::Ptr scoped = provider->createScope()

Service can be registered as a singleton, scoped, or transient.

  • Singleton: service provider will create only one instance of this service (accessible via the getService method)

  • Scoped: service provider will create only one instance of this service for each scope (accessible via the getService method)

  • Transient: services are always unique, a new instance is provided every time it is requested, and the service provider returns, in this case, std::unique_ptr (accessible via createService method)

Warning

Only transient services can be created using createService method otherwise the method will throw an exception

Only singleton/scoped services can be accessed using the getService method otherwise the method will throw an exception

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

using namespace sb::di;

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

template <class TService, bool Get> auto getOrCreate(IServiceProvider &provider)
{
    if constexpr (Get)
    {
        return &provider.getService<TService>();
    }
    else
    {
        return provider.createService<TService>();
    }
}

template <class TService, bool Get> void compareServices(IServiceProvider &root, IServiceProvider &scoped)
{
    std::cout << "rootProvider \t == rootProvider:\t"
              << (getOrCreate<TService, Get>(root) == getOrCreate<TService, Get>(root)) << std::endl;
    std::cout << "rootProvider \t == scopedProvider:\t"
              << (getOrCreate<TService, Get>(root) == getOrCreate<TService, Get>(scoped)) << std::endl;
    std::cout << "scopedProvider \t == scopedProvider:\t"
              << (getOrCreate<TService, Get>(scoped) == getOrCreate<TService, Get>(scoped)) << std::endl;
}

int main()
{
    IServiceProvider::Ptr rootProvider = ServiceCollection{}
                                             .addSingleton<SingletonService>()
                                             .addScoped<ScopedService>()
                                             .addTransient<TransientService>()
                                             .buildServiceProvider();

    // Accessing Services
    SingletonService &singleton = rootProvider->getService<SingletonService>();
    ScopedService &scoped = rootProvider->getService<ScopedService>();
    std::unique_ptr<TransientService> transient = rootProvider->createService<TransientService>();

    IServiceProvider::Ptr scopedProvider = rootProvider->createScope();

    std::cout << std::endl << "Singletons comparison" << std::endl;
    compareServices<SingletonService, true>(*rootProvider, *scopedProvider);

    std::cout << std::endl << "Scoped comparison" << std::endl;
    compareServices<ScopedService, true>(*rootProvider, *scopedProvider);

    std::cout << std::endl << "Transient comparison" << std::endl;
    compareServices<TransientService, false>(*rootProvider, *scopedProvider);
    return 0;
}
Output#
Singletons comparison
rootProvider     == rootProvider:       1
rootProvider     == scopedProvider:     1
scopedProvider   == scopedProvider:     1

Scoped comparison
rootProvider     == rootProvider:       1
rootProvider     == scopedProvider:     0
scopedProvider   == scopedProvider:     1

Transient comparison
rootProvider     == rootProvider:       0
rootProvider     == scopedProvider:     0
scopedProvider   == scopedProvider:     0