Services LifeTime

Service providers can create scoped service providers:

ServiceProvider provider = ServiceCollection{}.buildServiceProvider();

ServiceProvider scoped = provider.createScope()

Warning

Root/main service provider cannot be destroyed before its children scoped providers this can lead to undefined behavior

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: instance provider will create only one instance of this instance for each scope (accessible via the getService method)

  • Transient: services are always unique, a new service is provided every time it is requested (accessible via createService or createInstanceInPlace method)

Warning

Only transient services can be created using createInstance/createInstanceInPlace 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 <cassert>
#include <iostream>

using namespace sb::di;

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

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

    // Accessing services
    SingletonService &rootSingleton = rootProvider.getService<SingletonService>();
    ScopedService &rootScoped = rootProvider.getService<ScopedService>();
    std::unique_ptr<TransientService> rootTransient = rootProvider.createService<TransientService>();

    ServiceProvider scopedProvider = rootProvider.createScope();

    // Accessing scoped services
    SingletonService &singleton = scopedProvider.getService<SingletonService>();
    ScopedService &scoped = scopedProvider.getService<ScopedService>();
    std::unique_ptr<TransientService> transient = scopedProvider.createService<TransientService>();

    assert(&rootSingleton == &singleton); // The same service for root and scoped provider
    assert(&rootScoped != &scoped);       // Different service for root and scoped provider
    assert(rootTransient != transient);   // Always different service (trivially different unique ptrs)

    std::cout << "Service Addresses Table" << std::endl;
    std::cout << "\t\t\trootProvider\tscopedProvider" << std::endl;
    std::cout << "singleton\t" << &rootSingleton << "\t" << &singleton << std::endl;
    std::cout << "scoped\t\t" << &rootScoped << "\t" << &scoped << std::endl;
    std::cout << "transient\t" << rootTransient.get() << "\t" << transient.get() << std::endl;
    return 0;
}
Possible Output
Service Addresses Table
            rootProvider     scopedProvider
singleton   0x600003ed0088   0x600003ed0088
scoped      0x600003ed00a8   0x600003ed00f8
transient   0x600003ed00c0   0x600003ed0110