Skip to content

Controlling lifetime

Andreone edited this page May 11, 2017 · 7 revisions

Shared instances

When you register an instance, it is automatically supposed to be a single instance that will be shared accross the application through its entire lifespan.

ContainerBuilder builder;

auto configuration = std::make_shared< DispatcherConfiguration >();
builder.registerInstance(configuration);

auto container = builder.build();

auto resolvedConfiguration = container->resolve< DispatcherConfiguration >();
assert(resolvedConfiguration == configuration);

You can explicitly tell the container that an object should be created only once by using singleInstance.

ContainerBuilder builder;

builder.registerType< MessageDispatcher >()
       .as< IMessageDispatcher >()
       .singleInstance();

auto container = builder.build();

auto dispatcher1 = container->resolve< IMessageDispatcher >();
auto dispatcher2 = container->resolve< IMessageDispatcher >();
assert(dispatcher1 == dispatcher2);

Nested containers

Say you already have an instance of a Container, you can create a nested container from this one.

ContainerBuilder builder;

builder.registerType< MessageDispatcher >()
       .as< IMessageDispatcher >()
       .singleInstance();

// container is the instance of the container we already have built earlier
auto nestedContainer = builder.buildNestedContainerFrom(*container);

auto dispatcher = nestedContainer->resolve< IMessageDispatcher >();

Everything we registered in that nested container will only be resolvable inside of it.

You can even provide some components that are dependencies of other objects registered in a parent container.

Say we have a Persister that needs a Configuration.

class Persister
{
public:
    Persister(const std::shared_ptr< Configuration >& configuration)
    {
        if (configuration == nullptr)
            throw std::invalid_argument("configuration");
    }
};
ContainerBuilder builder;

builder.registerType< Persister >();

auto container = builder.build();

auto persister = container->resolve< Persister >();

The resolution of persister will throw because the constructor of Persister will be passed nullptr. Let's add the registration of configuration in a nested container.

ContainerBuilder anotherBuilder;

anotherBuilder.registerType< Configuration >();

auto nestedContainer = anotherBuilder.buildNestedContainerFrom(*container);

auto persister = nestedContainer->resolve< Persister >();

Now everything is fine if we resolve Persister from the nested container. If we did from our root container, we would have an exception since it still doesn't know about Configuration.

When the nested container is released, that is, we no longer have any reference on it, any resolved objects will remain alive as long as you keep references on them. But I am being obvious here by explaining shared pointers mechanisms right?