I read on this post that they are using dependency injection to load repository instance on each mvc request.
I\'m not sure if I understand correctly but I currentl
The main advantage of interfaces is that they encourage abstraction. If you want to mock a completely different implementation (for example, when performing unit testing, which you should be doing anyway :), you would just inject another implementation of the IUserRepository
to your UserController
constructor. This is, how I see it, one of the main advantages of using interfaces.
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
** You do not need default constructors in your controllers if you have controller factory implemented and set up.
The main idea behind DI is to force you to see the big picture instead of concrete implementations.
Your controller needs to get the user, but it shouldn't care about concrete implementation (does your repository fetch the user from the database, web service, xml file, etc. or does it use Linq2Sql, EntityFramework, Dapper or something else under the hood).
Your controller is dependent on that piece of code which can be injected in constructor, property or method, but it doesn't really care about concrete implementation.
DI removes the tight coupling between your controller and repository, allows you to write unit tests by mocking the repository, and you can easily change the concrete implementation of your repository (eg. use PetaPoco instead of EntityFramework) without touching the rest of the code.
You should also take a look at the SOLID principles: http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)