How to implement and register a custom dependency resolver in ASP.NET MVC 5

March 6, 2015, (updated on March 26, 2015), Software Development

The ASP.NET MVC 5 framework supports the integration of 3rd party dependency injection frameworks. This can be done by implementing the IDependencyResolver interface and registering an instance of the interface on application startup. The registration is made in the Application_Start method which can be found in the Global.asax.cs file:

protected void Application_Start()
{
    ...

    var compositionContext = new CompositionContext();
    compositionContext.AddPart<IMyService, MyServiceImpl>();
    // TODO: Register your own services here

    DependencyResolver.SetResolver(new MyDependencyResolver(compositionContext));
}

Most dependency injection frameworks provide a NuGet package which already contains an IDependencyResolver implementation (for example Ninject.MVC3). However, because I wanted to use the IoC container from my own library MyToolkit, I had to write the resolver from scratch:

public class MyDependencyResolver : IDependencyResolver
{
    private readonly CompositionContext _compositionContext;

    public MyDependencyResolver(CompositionContext compositionContext)
    {
        _compositionContext = compositionContext;

        var factory = new MyControllerFactory(_compositionContext);
        _compositionContext.AddPart<IControllerFactory, MyControllerFactory>(factory);
    }

    public object GetService(Type serviceType)
    {
        return _compositionContext.GetPart(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _compositionContext.GetParts(serviceType);
    }
}

As you can see, I also had to provide an implementation of the IControllerFactory interface which is used by the ASP.NET MVC framework to instantiate new controllers. Instead of directly implementing the interface, my implementation inherits from DefaultControllerFactory, so that I only had to override the GetControllerInstance method:

public class MyControllerFactory : DefaultControllerFactory
{
    private readonly CompositionContext _compositionContext;

    public MyControllerFactory(CompositionContext compositionContext)
    {
        _compositionContext = compositionContext;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        var constructor = controllerType.GetConstructors().First();

        var parameters = constructor
            .GetParameters()
            .Select(argument => _compositionContext.GetPart(argument.ParameterType, null))
            .ToArray();

        return (IController)constructor.Invoke(parameters);
    }
}

In the GetControllerInstance method, the first constructor is retrieved using reflection. After that, the appropriate service objects are resolved for each constructor parameter. In the last line, the controller is created using the parameters array.

Tweet about this on TwitterShare on FacebookEmail this to someoneShare on TumblrShare on LinkedIn

Tags: , , , , , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax