Lifetime Managers in Unity Container

The unity container manages the lifetime of objects of all the dependencies that it resolves using lifetime managers.

Unity container includes different lifetime managers for different purposes. You can specify lifetime manager in RegisterType() method at the time of registering type-mapping. For example, the following code snippet shows registering a type-mapping with TransientLifetimeManager.

var container = new UnityContainer()
                   .RegisterType<ICar, BMW>(new TransientLifetimeManager());

The following table lists all the lifetime managers:

Lifetime Manager Description
TransientLifetimeManager Creates a new object of requested type every time you call Resolve or ResolveAll method.
ContainerControlledLifetimeManager Creates a singleton object first time you call Resolve or ResolveAll method and then returns the same object on subsequent Resolve or ResolveAll call.
HierarchicalLifetimeManager Same as ContainerControlledLifetimeManager, the only difference is that child container can create its own singleton object. Parent and child container do not share singleton object.
PerResolveLifetimeManager Similar to TransientLifetimeManager but it reuses the same object of registered type in the recursive object graph.
PerThreadLifetimeManager Creates singleton object per thread basis. It returns different objects from the container on different threads.
ExternallyControlledLifetimeManager It manintains only weak reference of objects it creates when you call Resolve or ResolveAll method. It does not maintain the lifetime of strong objects it creates and allow you or garbage collector to control the lifetime. It enables you to create your own custom lifetime manager

Let's understand each lifetime manager using the following example classes.

public interface ICar
{
    int Run();
}

public class BMW : ICar
{
    private int _miles = 0;

    public int Run()
    {
        return ++_miles;
    }
}

public class Ford : ICar
{
    private int _miles = 0;
    public int Run()
    {
        return ++_miles;
    }
}

public class Audi : ICar
{
    private int _miles = 0;

    public int Run()
    {
        return ++_miles;
    }
}

public class Driver
{
    private ICar _car = null;

    public Driver(ICar car)
    {
        _car = car;
    }

    public void RunCar()
    {
        Console.WriteLine("Running {0} - {1} mile ", _car.GetType().Name, _car.Run());
    }
}

TransientLifetimeManager

TransientLifetimeManager is the default lifetime manager. It creates a new object of requested type every time you call Resolve() or ResolveAll() method.

var container = new UnityContainer()
                   .RegisterType<ICar, BMW>();

var driver1 = container.Resolve<Driver>();
driver1.RunCar();

var driver2 = container.Resolve<Driver>();
driver2.RunCar();
Output:
Running BMW - 1 Mile
Running BMW - 1 Mile

In the above example, unity container will create two new instances of BMW class and injects into driver1 and driver2 object. This is because the default lifetime manager is TransientLifetimeManager which creates new dependent object every time you call Resolve or ResolveAll method. You can specify the lifetime manager at the time of registering type using RegisterType() method.

The following example will display same output as above example because TransientLifetimeManager is the default manager if not specified.

var container = new UnityContainer()
                   .RegisterType<ICar, BMW>(new TransientLifetimeManager());

var driver1 = container.Resolve<Driver>();
driver1.RunCar();

var driver2 = container.Resolve<Driver>();
driver2.RunCar();
Output:
Running BMW - 1 Mile
Running BMW - 1 Mile

ContainerControlledLifetimeManager

Use ContainerControlledLifetimeManager when you want to create a singleton instance.

var container = new UnityContainer()
                   .RegisterType<ICar, BMW>(new ContainerControlledLifetimeManager());

var driver1 = container.Resolve<Driver>();
driver1.RunCar();

var driver2 = container.Resolve<Driver>();
driver2.RunCar();
Output:
Running BMW - 1 mile
Running BMW - 2 mile

In the above example, we specified ContainerControlledLifetimeManager in RegisterType() method. So unity container will create a single instance of BMW class and inject it in all the instances of Driver.

HierarchicalLifetimeManager

The HierarchicalLifetimeManager is the same as ContainerControlledLifetimeManager except that if you create a child container then it will create its own singleton instance of registered type and will not share instance with parent container.

var container = new UnityContainer()
                   .RegisterType<ICar, BMW>(new HierarchicalLifetimeManager());

var childContainer = container.CreateChildContainer();
            
var driver1 = container.Resolve<Driver>();
driver1.RunCar();

var driver2 = container.Resolve<Driver>();
driver2.RunCar();

var driver3 = childContainer.Resolve<Driver>();
driver3.RunCar();

var driver4 = childContainer.Resolve<Driver>();
driver4.RunCar();
Output:
Running BMW - 1 mile
Running BMW - 2 mile
Running BMW - 1 Mile
Running BMW - 2 Mile

As you can see, container and childContainer have their own singleton instance of BMW.

Visit Understand Lifetime Managers to learn more about it.