How to setup Dependency Injection with Microsoft Unity in Asp.net Mvc
Dependency Injection (DI) is a pretty great technique that will help you decouple a service from a client. The way it works, is that when a client is created a service will be applied in the instantiation of the client, so that it holds a reference to the service. You can of course inject multiple services, if you want to.
The description of DI might be a bit vague, because the term service seems to be used for anything these days. I hope the examples will shed some light on it.
Let’s see how things will look like without DI - This can of course be done a bit differently, but for the sake of the example we will just keep it like this.
1 2 3 4 5 6 7 8 9 | public class HomeController : Controller { public void Index() { ISomeRepository repo = new SomeRepository(); ViewData["content"] = repo.FindContent(); return View(); } } |
Let’s move on to an example where DI comes into play.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class HomeController : Controller { private ISomeRepository repo; public HomeController(ISomeRepository someRepository) { repo = someRepository; } public void Index() { ViewData["content"] = repo.FindContent(); return View(); } } |
We need to do a little bit more than this. So let’s download Unity from Microsoft and include it in our project. Then we can create a new ControllerFactory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class UnityControllerFactory : DefaultControllerFactory { private readonly IUnityContainer _container; public UnityControllerFactory(IUnityContainer container) { _container = container; } protected override IController GetControllerInstance(Type controllerType) { if (controllerType == null) { throw new HttpException(0x194, "No Controller Found"); } if (!typeof(IController).IsAssignableFrom(controllerType)) { throw new ArgumentException("TypeDoesNotSubclassControllerBase", "controllerType"); } return _container.Resolve(controllerType) as IController; } } |
So far, so good. We will now set it up in the Global.asax file. Of course, you will need to create some sort of service, if you want to test this. In my example I assume that I have a service called SomeRepository available to me, which implements the interface ISomeRepository.
1 2 3 4 5 6 7 8 | protected void Application_Start() { IUnityContainer container = new UnityContainer(); container.RegisterType<ISomeRepository, SomeRepository>(); UnityControllerFactory factory = new UnityControllerFactory(container); ControllerBuilder.Current.SetControllerFactory(factory); } |
That’s it! You have now injected your first service into a Controller.
The great thing about this is that you can now unit test your controllers with a mock implementation of a service, as long as it implements the interface.
If you have been using MonoRail, then you probably know about Windsor, so if you don’t like to use Unity, you can easily switch Unity out.
Ps. Using DI can be a good thing, but using it extensively can make things too complex, which is a bad thing.