When my team started using dependency injection we were reading a good book "Pro ASP.NET MVC 2 Framework" by Steven Sanderson. In this book he describes how to work with Castle Windsor, a popular dependency injection framework. In another book "Pro ASP.NET MVC 3 Framework", as I know, how to use Ninject (another framework) is described.
In order to use Castle Windsor:
First you have to write your custom implementation of controller factory:
/// <summary>
/// Controller factory the class is to be used to eliminate hard-coded dependencies
/// between controllers and other components
/// </summary>
public class ControllerFactory : DefaultControllerFactory
{
private readonly IWindsorContainer container;
public WindsorControllerFactory(IWindsorContainer container)
{
this.container = container;
}
public override void ReleaseController(IController controller)
{
container.Release(controller.GetType());
}
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
return (IController)container.Resolve(controllerType);
}
}
Then you have to write an installer for all your controllers.
/// <summary>
/// Castle windsor installer for controller components.
/// </summary>
public class ControllersInstaller : IWindsorInstaller
{
/// <summary>
/// Performs the installation in the <see cref="T:Castle.Windsor.IWindsorContainer"/>.
/// </summary>
/// <param name="container">The container.</param>
/// <param name="store">The configuration store.</param>
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Classes.FromThisAssembly()
.BasedOn<IController>()
.LifestyleTransient()
);
}
}
If you want your repositories to be resolved as dependencies you should write an installer for them also. It will be similar to ControllersInstaller but lifestyle will be LifestylePerWebRequest(). PerRequestLifestyle should be registered in web.config file.
<httpModules>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
</httpModules>
And then you have to create an instance of container when application starts in Global.asax.cs:
public class MvcApplication : System.Web.HttpApplication
{
private static IWindsorContainer container;
protected void Application_Start()
{
container = new WindsorContainer();
container.Install(FromAssembly.This());
//Set the controller builder to use our custom controller factory
var controllerFactory = new WindsorControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
protected void Application_End()
{
container.Dispose();
}
}
There is also a link to Castle Windsor documentation where you can find more information about working with lifestyles and ASP.NET MVC 3 application tutorial.
** When you use interfaces
- it is easier to mock dependencies in your code (some mocking frameworks have restrictions)
- it is easier to develop new implementation and test it without changes in old one.
** You do not need default constructors in your controllers if you have controller factory implemented and set up.