In this post we will see 2 important things.
- Using Unity Dependency Resolver
- What is Lifetime manager and its significance.
Step 1: Create a regular MVC web application. create a new separate class library project. Add a two new interfaces and their concrete classes.
Step 2: Now, as per Dependency Injection principle (constructor injection), the dependee object will be passed as a parameter to the dependent class constructor. The same is implemented with Home controller.
private readonly IEmployee _employee;
private readonly IEmployer _employer;
public HomeController(IEmployee employee, IEmployer employer)
{
_employee = employee;
_employer = employer;
}
But, you know that DefautControllerFactory expects a parameter-less constructor to instantiate the object for a controller. So, this implementation will cause a run-time exception.
Step 3: This is where Unity framework comes into picture. Using unity 2.0 , all the dependencies can be resolved thus addressing all the dependency issues.
Unity 2.0 dll can be downloaded from:
Unity2.0
Step 4: There are a few steps which we need to implement.
- Add the Unity dlls to project.
- Microsoft.Practices.Unity
- Microsoft.Practices.Unity.Configuration
- Microsoft.Practices.Unity.Interception
- Microsoft.Practices.Unity.Interception.Configuration
- Define UnityDependencyReolver class.
public class UnityDependencyResolver : IDependencyResolver
{
private IUnityContainer container;
public UnityDependencyResolver(IUnityContainer container)
{
this.container = container;
}
public object GetService(Type serviceType)
{
if (!container.IsRegistered(serviceType))
{
if (serviceType.IsAbstract || serviceType.IsInterface)
{
return null;
}
}
return container.Resolve(serviceType);
}
public IEnumerable GetServices(Type serviceType)
{
return container.ResolveAll(serviceType);
}
}
- Register the dependencies with Unity container.
var container = new UnityContainer();
container.RegisterType<IEmployee, employee="">();
container.RegisterType<IEmployer, employer="">();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
Usually above code will reside in global.ascx.cs file inside App_Start() method. But in real time, the no of dependencies will increase thus effecting readability of file. So, i used to isolate all the above code into a additional method "RegisterAll()" in Unity dependency resolver class.
Now, execute and see the result.
application getting executed and the code in Home controller's Index() method executed.
public ActionResult Index()
{
ViewBag.Message = "Execution Success";
return View();
}
Step 5: Before looking into life time manager, lets do a small experiment. Let us modify the class files "Employee" and "Employer" as shown below.
Employee class definition:
public class Employee: IEmployee
{
private string _key;
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string EmployeeAddress { get; set; }
public Employee()
{
_key = Guid.NewGuid().ToString();
}
public string Getkey()
{
return _key;
}
}
Employer class definition:
public class Employer: IEmployer
{
private string _key;
public string EmployerName { get; set; }
public string EmployerAddress { get; set; }
public List<Employee> EmployeeList { get; set; }
public Employer()
{
_key =Guid.NewGuid().ToString();
}
public string Getkey()
{
return _key;
}
}
From above definitions, we can see that the GetKey() method will return a unique key every time when a new instance is created for the class.
Step 6: A small change has to be done in Index() action method as well. Instead of a simple success message, i will send the key's of both the instances.
public ActionResult Index()
{
ViewBag.Message = "Time Stamp : "+DateTime.Now.ToString()+Environment.NewLine+
" Employee Key : "+_employee.Getkey()+Environment.NewLine+
" Employer Key : "+_employer.Getkey();
return View();
}
Now see the result by pressing refresh button multiple times.
Refresh 1:
Refresh 2:
Now you can see that the key-id keep on changing. This means, every time when unity resolved the dependency, it will create a fresh instance of both Employee and Employer class.
Reason: When you register a type in configuration, or by using the RegisterType
method, the default behavior is for the container to use a transient lifetime manager. It creates a new instance of the registered, mapped, or requested type each time you call the Resolve
or ResolveAll
method or when the dependency mechanism injects instances into other classes. The container does not store a reference to the object.
Step 7: Just imagine if you are dealing with real time project which might have 1000 dependencies to resolve, and a 1000 new instances are getting created for every request. It will hit the performance.
This is where "LifetimeManager" will pitch in. Unity uses specific types that inherit from the LifetimeManager
base class (collectively referred to as lifetime managers) to control how it stores references to object instances and how the container disposes of these instances.
Step 8: Before looking into types of LifetimeManagers, lets tweak our code a bit and see the results.
Change RegisterAll() method a bit and see the difference.
public static void RegisterAll()
{
var container = new UnityContainer();
container.RegisterType<IEmployee, Employee>
(new ContainerControlledLifetimeManager());
container.RegisterType<IEmployer, Employer>
(new ContainerControlledLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
See the output by refreshing contentiously:
Refresh 1:
Refresh 2:
Now you can see that the key remained same even when time stamp changed.
This means Unity is maintaining the reference to existing instances, thus using them instead of re-creating them.
There are 6 types of Lifetime Managers available to work with.
TransientLifetimeManager
. For this lifetime manager Unity creates and returns a new instance of the requested type for each call to the Resolve
or ResolveAll
method. This lifetime manager is used by default for all types registered using the RegisterType
, method unless you specify a different lifetime manager.
ContainerControlledLifetimeManager
which registers an existing object as a singleton instance. For this lifetime manager Unity returns the same instance of the registered type or object each time you call the Resolve
or ResolveAll
method or when the dependency mechanism injects instances into other classes.
HierarchicalLifetimeManager.
For this lifetime manager, as for the ContainerControlledLifetimeManager,
Unity returns the same instance of the registered type or object each time you call the Resolve
or ResolveAll
method or when the dependency mechanism injects instances into other classes. The distinction is that when there are child containers, each child resolves its own instance of the object and does not share one with the parent. When resolving in the parent, the behavior is like a container controlled lifetime; when resolving the parent and the child you have different instances with each acting as a container-controlled lifetime.
PerResolveLifetimeManager
. For this lifetime manager the behavior is like a TransientLifetimeManager
, but also provides a signal to the default build plan, marking the type so that instances are reused across the build-up object graph. In the case of recursion, the singleton behavior applies where the object has been registered with the PerResolveLifetimeManager
. The following example uses the PerResolveLifetimeManager
.
PerThreadLifetimeManager
. For this lifetime manager Unity returns, on a per-thread basis, the same instance of the registered type or object each time you call the Resolve
or ResolveAll
method or when the dependency mechanism injects instances into other classes. This lifetime manager effectively implements a singleton behavior for objects on a per-thread basis. PerThreadLifetimeManager
returns different objects from the container for each thread.
ExternallyControlledLifetimeManager
. The ExternallyControlled LifetimeManager
class provides generic support for externally managed lifetimes. This lifetime manager allows you to register type mappings and existing objects with the container so that it maintains only a weak reference to the objects it creates when you call the Resolve
or ResolveAll
method or when the dependency mechanism injects instances into other classes based on attributes or constructor parameters within that class. This allows other code to maintain the object in memory or dispose it and enables you to maintain control of the lifetime of existing objects or allow some other mechanism to control the lifetime.
With this we have seen how to resolve Dependencies using Unity frame work and significance of Lifetime Managers. Lets take a deep dive into different Lifetime Managers by implementing them practically.
Code Sample:
Unity with Lifetime Manager
Is it helpful for you? Kindly let me know your comments / Questions.