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.
Rico Suter
SOFTWARE ENGINEERING
EDIT
.NET ASP.NET ASP.NET MVC ASP.NET MVC 5 Dependency Injection MyToolkit Reflection Web