Lifetime Managers in Unity Container
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 the lifetime manager in the RegisterType()
method at the time of registering type-mapping. For example, the following code snippet shows how to register 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 the requested type every time you call the Resolve or ResolveAll method. |
ContainerControlledLifetimeManager | Creates a singleton object first time you call the Resolve or ResolveAll method and then returns the same object on subsequent Resolve or ResolveAll calls. |
HierarchicalLifetimeManager | Same as the ContainerControlledLifetimeManager, the only difference is that the child container can create its own singleton object. The parent and child containers do not share the same singleton object. |
PerResolveLifetimeManager | Similar to the TransientLifetimeManager, but it reuses the same object of registered type in the recursive object graph. |
PerThreadLifetimeManager | Creates a singleton object per thread. It returns different objects from the container on different threads. |
ExternallyControlledLifetimeManager | It maintains only a weak reference of the objects it creates when you call the Resolve or ResolveAll method. It does not maintain the lifetime of the strong objects it creates, and allows you or the garbage collector to control the lifetime of the objects. 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
The TransientLifetimeManager
is the default lifetime manager. It creates a new object of the requested type every time you call the 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();
Running BMW - 1 Mile
In the above example, Unity container will create two new instances of the BMW
class and will inject into the driver1
and driver2
objects. This is because the default lifetime manager is TransientLifetimeManager
, which creates a new dependent object every time you call the Resolve()
or ResolveAll()
method. You can specify the lifetime manager when registering the type using the RegisterType()
method.
The following example will display the same output as in 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();
Running BMW - 1 Mile
ContainerControlledLifetimeManager
Use the 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();
Running BMW - 2 mile
In the above example, we specified ContainerControlledLifetimeManager
in the RegisterType()
method. So, Unity container will create a single instance of the BMW
class and inject it in all the instances of Driver
.
HierarchicalLifetimeManager
The HierarchicalLifetimeManager
is the same as the ContainerControlledLifetimeManager
, except that if you create a child container then it will create its own singleton instance of the registered type and will not share the instance with the 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();
Running BMW - 2 mile
Running BMW - 1 Mile
Running BMW - 2 Mile
As you can see, both container and childContainer have their own singleton instance of BMW
.
Visit Understand Lifetime Managers to learn more about it.