Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using DI to load repository instance on each mvc request

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 currently using in my mvc app. UserRepository which implements IUserRepository interface. This interface is injected in controller constructor

public class UserController : Controller
{
   private IUserRepository repository;
   public UserController(IUserRepository rep)
   { repository = rep; }

   public UserController() : this(new UserRepository()) {}
}

but I don't see any benefit using this interface (IUserRepository) I could use UserRepository without interface. Obviously someone smarter is figured that is right approach (I've found it on apress mvc4 book) and I would kindly ask someone to elaborate why is this better approach instead of using repository without interface.

Having this in mind I would ask anyone to share concrete examples or links on how to implement this approach (using dependency injection to load repository instance on each mvc request).

like image 249
user2783193 Avatar asked Dec 19 '22 23:12

user2783193


2 Answers

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)

like image 110
šljaker Avatar answered Dec 29 '22 12:12

šljaker


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

  1. it is easier to mock dependencies in your code (some mocking frameworks have restrictions)
  2. 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.

like image 20
Ilya Palkin Avatar answered Dec 29 '22 13:12

Ilya Palkin