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.