ASP.NET MVC Tip: Dependency Injection with Unity Application Block
In my earlier post, I have explained how to use dependency injection pattern in ASP.net MVC application using StructureMap. In this post, I demonstrate how you can use dependency injection pattern using Microsoft’s Unity Application Block (Unity). If you want to develop an ASP.NET MVC application fully with Microsoft stack, you can use Unity Application Block to perform dependency injection.Unity is a cool dependency injection container and I hope that it will become more powerful in the future releases.
Introduction to Unity
Unity is a lightweight, extensible dependency injection container that provides the support for constructor, property, and method call injection. Unity has a service location capability that allows the ASP.NET developer to store or cache the container in the ASP.NET session, application or per Request.
Register Dependencies
Unity provides two methods for registering types and mappings with the container. The RegisterType method registers a type with the container and the RegisterInstance method registers with the container an existing instance of a type.
IUnityContainer container = new UnityContainer(); container.RegisterType<ICategoryRepository, CategoryRepository>();
The above code tells the Unity Container that, to inject the instance of CategoryRepository when there is a request for ICategoryRepository and the container will create a new instance of CategoryRepository every time when there is request for ICategoryRepository. The default behavior is for the container to use a transient lifetime manager and the container will not store or cache a reference to the object. If you want singleton behavior for objects, you have to register a LifetimeManager. A lifetime manager controls how stores references to object instances and reused within the container.
IUnityContainer container = new UnityContainer(); container.RegisterType<ICategoryRepository, CategoryRepository>(new ContainerControlledLifetimeManager());
The above registration specify that any time an instance of ICategoryRepository is requested, you will get back the same instance of CategoryRepository as long as the container is alive. The container will create a new instance at the time of first request and will be use the same instance for the later requests. The ContainerControlledLifeTimeManager class provides the singleton behavior for the container.
You can create your own custom LifetimeManager class derive from LifetimeManager class. The important methods of LifetimeManager class are GetValue that returns the instance, SetValue method store the instance value and RemoveValue method reomove the instance from the container.
public abstract class LifetimeManager : ILifetimePolicy
{
public abstract object GetValue();
public abstract void SetValue(object newValue);
public abstract void RemoveValue();
}
Use Unity with an ASP.NET MVC application
In this tip, I show how you can use the Unity Application Block to perform Dependency Injection within an ASP.NET MVC application. In this tip, I will show you how to perform constructor injection. Constructor Injection will push dependencies into a concrete class through constructor arguments.
The below code listings show that a controller class and its dependent classes.
Listing 1 – CategoryController
public class CategoryController : Controller { ICategoryService _categoryService = null; //Inject instance of CategoryService using construction injection public CategoryController(ICategoryService categoryService) { _categoryService = categoryService; } /// <summary> /// /// </summary> /// <param name="page"></param> /// <returns></returns> [AcceptVerbs(HttpVerbs.Get)] public ActionResult List(int? page) { var categories = _categoryService.GetCategories(page ?? 0, 10); return View(categories); } }
Listing 2 – ICategoryService
public interface ICategoryService { PagedList<Category> GetCategories(int pageIndex,int pageSize); }
Listing 3 – CategoryService
public class CategoryService : ICategoryService { ICategoryRepository _repository = null; /// <summary> /// Creates a CategoryService based on the passed-in repository /// </summary> /// <param name="repository">An ICategoryRepository</param> public CategoryService(ICategoryRepository repository) { _repository = repository; if (_repository == null) throw new InvalidOperationException("Repository cannot be null"); } public PagedList<Category> GetCategories(int pageIndex,int pageSize) { return _repository.GetCategories(). ToPagedList<Category>(pageIndex, pageSize); } }
Listing 4 – ICategoryRepository
public interface ICategoryRepository { IQueryable<Category> GetCategories(); }
Listing 5 – CategoryRepository
public class CategoryRepository : ICategoryRepository { myFinanceData _db; public CategoryRepository(myFinanceData data) { _db = data; } /// <summary> /// Linq To Sql implementation for Categories /// </summary> /// <returns>IQueryable of Categories</returns> public IQueryable<Category> GetCategories() { return from c in _db.DataContext.Categories select new Category { ID=c.ID, Name=c.Name, Description=c.Description, CategoryType = c.CategoryType }; } }
Listing 6 – myFinanceData
public class myFinanceData { private myFinanceDataContext dataContext; public myFinanceDataContext DataContext { get { if (dataContext == null) { dataContext = new myFinanceDataContext(); } return dataContext; } } }
Depedencies
The CategoryController has a dependency with ICategoryService. The concrete implementation of ICategoryService, i.e. CategoryService has a dependency with ICategoryRepository. The concrete implementation of ICategoryRepository, i.e. CategoryRepository has a dependency with myFinanceData. When we calling action methods of Category controller, we need to create objects of CategoryService, CategoryRepository and myFinanceData.
The below steps will configure Unity to perform constructor injection in our ASP.NET MVC application.
Step 1 – Add reference for Unity Application Block
Add a reference to Microsoft.Practices.Unity.dll and Microsoft.Practices.ObjectBuilder2.
You can download Unity from http://www.codeplex.com/unity
Step 2 – Custom LifetimeManager class
Unity provides the functionality to specify the location of instance. This functionality is very useful for the ASP.NET applications where we can store or cache the container in the HttpContext, HttpSession or HttpApplication. In this tip, I used to store the container in current HttpContext. In the below code, I am creating a custom lifetime manager to store container in the current HttpContext.
public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable { public override object GetValue() { return HttpContext.Current.Items[typeof(T).AssemblyQualifiedName]; } public override void RemoveValue() { HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName); } public override void SetValue(object newValue) { HttpContext.Current.Items[typeof(T).AssemblyQualifiedName] = newValue; } public void Dispose() { RemoveValue(); }
Step 3 – Controller Factory for Unity
public class UnityControllerFactory : DefaultControllerFactory { IUnityContainer container; public UnityControllerFactory(IUnityContainer container) { this.container = container; } protected override IController GetControllerInstance(Type controllerType) { try { if (controllerType == null) throw new ArgumentNullException("controllerType"); if (!typeof(IController).IsAssignableFrom(controllerType)) throw new ArgumentException(string.Format( "Type requested is not a controller: {0}", controllerType.Name), "controllerType"); return container.Resolve(controllerType) as IController; } catch { return null; } } }
The controller factory is responsible for creating controller instances.We extend the built in default controller factory with our own factory for working Unity with ASP.NET MVC.
Step 4 – Register Types and Set Controller Factory
public static class Bootstrapper { public static void ConfigureStructureMap() { StructureMap.StructureMapConfiguration.AddRegistry(new DBServiceRegistry()); StructureMap.StructureMapConfiguration.AddRegistry(new DInjRegistry()); IUnityContainer container = new UnityContainer(); container.RegisterType<ICategoryRepository, CategoryRepository>(new ContainerControlledLifetimeManager()); } public static void ConfigureUnityContainer() { IUnityContainer container = new UnityContainer(); // Registrations container.RegisterType<myFinanceData, myFinanceData> (new HttpContextLifetimeManager<myFinanceData>()); container.RegisterType<ICategoryRepository, CategoryRepository> (new HttpContextLifetimeManager<ICategoryRepository>()); container.RegisterType<ICategoryService, CategoryService> (new HttpContextLifetimeManager<ICategoryService>()); ControllerBuilder.Current.SetControllerFactory( new myFinance.Web.Controllers.UnityControllerFactory(container)); } }
The above Unity configuration specified in the ConfigureUnityContainer method, tells to inject CategoryService when there is a request for ICategoryService. And also inject CategoryRepository when there is a request for ICategoryRepository. The CategoryRepository class has a dependency with myFinanceData. So we configure that inject the instance of myFinanceData when there is request for myFinanceData. The above code also set the controller factory for working with Unity.
Step 5 – Modify Global.asax.cs for configure Unity container
protected void Application_Start() { RegisterRoutes(RouteTable.Routes); //Configure for Dependecny Injection using Unity Bootstrapper.ConfigureUnityContainer(); }
The above code will set the configuration for the Unity container when our ASP.NET MVC application is started. The Bootstrapper class is specified in the Step 4.
Summary
In this tip, I demonstrated how you can use the Unity Application Block to perform Dependency Injection within an ASP.NET MVC application. The Unity Application Block allows us to develop highly loosely coupled ASP.NET MVC applications using fully with Microsoft stack.