Rico Suter's blog.
 


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.



Discussion