ASP.NET MVC3提供了IDependencyResolver接口,实现该接口,并结合相应的“依赖注入容器”(比如:Unity)可以方便地对Controller进行依赖注入。
本文以Unity为例,说明一下实现IDependencyResolver接口需要注意的地方。
先看一下我们使用的实现代码:
namespace CNBlogs.Infrastructure.CrossCutting.IoC
{
public class IoCDependencyResolver : IDependencyResolver
{
#region Memebers
private IContainer _currentContainter;
#endregion
#region Constructors
public IoCDependencyResolver(IContainer container)
{
_currentContainter = container;
}
#endregion
#region IDependencyResolver Members
public object GetService(Type serviceType)
{
return _currentContainter.Resolve(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _currentContainter.ResolveAll(serviceType);
}
#endregion
}
}
这样实现后,访问时出现下面的错误:
The current type, System.Web.Mvc.IControllerFactory, is an interface and cannot be constructed.
Are you missing a type mapping
从这个错误可以分析出,ASP.NET MVC试图通过Unity解析IControllerFactory的实现,但我们在代码中并没有注册IControllerFactory的实现。
于是,我们手动注册一下,代码如下:
_currentContainer.RegisterType<IControllerFactory, DefaultControllerFactory>();
之前的错误消失了,却出现了新的错误:
The current type, System.Web.Mvc.IControllerActivator, is an interface and cannot be constructed.
Are you missing a type mapping?
又找不到另外一个接口(IControllerActivator)的实现,难道要手工一个一个注册?
看来这不是解决之道,需要另辟捷径...
在codeplex中发现了Unity.MVC3(也是通过Unity实现ASP.NET MVC Contorller的依赖注入),学习了一下它的代码,发现了解决之道。
原来只需在IDependencyResolver.GetService(Type serviceType)的实现中,判断一下serviceType是否被注册,如果没有被注册,就返回null。ASP.NET MVC得到null返回值,会自己解析这个接口,这样问题就解决了,代码如下:
public object GetService(Type serviceType)
{
if (!_currentContainter.IsRegistered(serviceType))
{
return null;
}
return _currentContainter.Resolve(serviceType);
}