简单剖析Asp.Net MVC 源码中的三个IoC注入点
注:本文所指MVC框架特指Asp.Net MVC 3.0,文中若有不当之处,请多加包涵,谢谢!
尊重他人原创,转载请务必注明来自http://www.cnblogs.com/Raoh/archive/2013/03/27/AspNetMvc_IOC.html
我们在做Asp.Net MVC依赖注入的时候,注入点主要有三个地方,分列如下:
1.实现了IControllerFactory接口的DefaultControllerFactory;
2.实现了IDependencyResolver接口的DefaultDependencyResolver;
3.实现了IControllerActivator接口的DefaultControllerActivator;
下面,我们简单剖析下这三个注入点的框架源码:
首先,MVC框架的Controller激活(实例化)过程是由IControllerFactory实现的,
IControllerFactory的源码如下:
public interface IControllerFactory { IController CreateController(RequestContext requestContext, string controllerName); SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName); void ReleaseController(IController controller); }
MVC框架中该接口的默认实现是DefaultControllerFactory,由DefaultControllerFactory的GetControllerInstance方法返回一个Controller实例(注意:可以将这里做为第一个依赖注入点),该方法的源码实现如下:
protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType) { if (controllerType == null) { throw new HttpException(404, String.Format( CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_NoControllerFound, requestContext.HttpContext.Request.Path)); } if (!typeof(IController).IsAssignableFrom(controllerType)) { throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_TypeDoesNotSubclassControllerBase, controllerType), "controllerType"); } return ControllerActivator.Create(requestContext, controllerType); }
跟踪源码,我们会发现,该方法中的ControllerActivator定义如下:
private IControllerActivator ControllerActivator { get { if (_controllerActivator != null) { return _controllerActivator; } _controllerActivator = _activatorResolver.Current; return _controllerActivator; } }
跟踪到这里,可以发现该方法的默认实现需要一个IControllerActivator,而其实现指向_activatorResolver.Current,继续跟踪源码,发现_activatorResolver是在DefaultControllerFactory的构造函数中实例化的,其默认指向SingleServiceResolver<IControllerActivator>,其源码如下:
internal DefaultControllerFactory(IControllerActivator controllerActivator, IResolver<IControllerActivator> activatorResolver, IDependencyResolver dependencyResolver) { if (controllerActivator != null) { _controllerActivator = controllerActivator; } else { _activatorResolver = activatorResolver ?? new SingleServiceResolver<IControllerActivator>( () => null, new DefaultControllerActivator(dependencyResolver), "DefaultControllerFactory contstructor" ); } }
其中SingleServiceResolver<IControllerActivator>构造函数中的第二个参数,new DefaultControllerActivator(dependencyResolver),就是_activatorResolver.Current,也就是IControllerActivator的默认实现,IControllerActivator的源码如下:
public interface IControllerActivator { IController Create(RequestContext requestContext, Type controllerType); }
该接口仅仅包含一个返回IController的Create方法。(注意:可以将这里做为第二个依赖注入点)
回头来看看DefaultControllerActivator的源码如下:
private class DefaultControllerActivator : IControllerActivator { Func<IDependencyResolver> _resolverThunk; public DefaultControllerActivator() : this(null) { } public DefaultControllerActivator(IDependencyResolver resolver) { if (resolver == null) { _resolverThunk = () => DependencyResolver.Current; } else { _resolverThunk = () => resolver; } } public IController Create(RequestContext requestContext, Type controllerType) { try { return (IController)(_resolverThunk().GetService(controllerType) ?? Activator.CreateInstance(controllerType)); } catch (Exception ex) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_ErrorCreatingController, controllerType), ex); } } }
阅读源码,我们会发现,该方法需要一个IDependencyResolver,IDependencyResolver的源码如下:
public interface IDependencyResolver { object GetService(Type serviceType); IEnumerable<object> GetServices(Type serviceType); }
而在DefaultControllerActivator的构造函数中,IDependencyResolver指向DependencyResolver.Current,通过跟踪代码我们会发现DependencyResolver.Current最终指向DefaultDependencyResolver的实例,框架中IDependencyResolver的默认实现就是DefaultDependencyResolver,其源码如下:
private class DefaultDependencyResolver : IDependencyResolver { [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This method might throw exceptions whose type we cannot strongly link against; namely, ActivationException from common service locator")] public object GetService(Type serviceType) { try { return Activator.CreateInstance(serviceType); } catch { return null; } } public IEnumerable<object> GetServices(Type serviceType) { return Enumerable.Empty<object>(); } }
最终由DefaultDependencyResolver的GetService返回一个Controller实例。(注意:可以将这里做为第三个依赖注入点)
后面有空的话,我会写一些代码示例,简单演示对这三个IoC注入点进行注入。
注:尊重他人原创,转载请务必注明来自http://www.cnblogs.com/Raoh/archive/2013/03/27/AspNetMvc_IOC.html