asp.net mvc源码分析-Controllerl篇 怎么创建Controller实例

asp.net mvc源码分析-Controllerl篇 如何创建Controller实例在上一篇文章asp.net mvc源码分析-路由篇 如何

asp.net mvc源码分析-Controllerl篇 如何创建Controller实例

在上一篇文章asp.net mvc源码分析-路由篇 如何找到 IHttpHandler中最后提到了MvcHandler,来上我们看看它的定义

 public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState

它有几个比较重要的属性:

internal ControllerBuilder ControllerBuilder  ,ControllerBuilder 类主要负责创建IControllerFactory

public RequestContext RequestContext,RequestContext是对这次请求的HttpContext(httpContext类)和RouteData的包装

而它的BeginProcessRequest方法中有几句比较重要的代码:

IControllerFactory factory;
ProcessRequestInit(httpContext, out controller, out factory);
IAsyncController asyncController = controller as IAsyncController;
if (asyncController != null) {
}
else
{
  Action action = delegate {
                        try {
                            controller.Execute(RequestContext);
                        }
                        finally {
                            factory.ReleaseController(controller);
                        }
 return AsyncResultWrapper.BeginSynchronous(callback, state, action, _processRequestTag);
}

在这篇文章中我们主要关心ProcessRequestInit(httpContext, out controller, out factory);    如何创建controller

ProcessRequestInit方法大致如下:

  private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory) {
            string controllerName = RequestContext.RouteData.GetRequiredString("controller");
            factory = ControllerBuilder.GetControllerFactory();
            controller = factory.CreateController(RequestContext, controllerName);
  }

         string controllerName = RequestContext.RouteData.GetRequiredString("controller");这句很简单获取Controller的名称,RouteData是当前路由数据,里面的key包括我们注册是的url格式  "{controller}/{action}/{id}",  和默认的defaults=new { controller = "Home", action = "Index", id = UrlParameter.Optional } 

现在大家知道为什么了我上一篇文章提到{controller}/{action}是必须得了吧。

现在让我们来看看ControllerBuilder的主要代码:

 public ControllerBuilder()            : this(null) {        }        internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver) {            _serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(                () => _factoryThunk(),                 new DefaultControllerFactory { ControllerBuilder = this },                "ControllerBuilder.GetControllerFactory"            );        }        public static ControllerBuilder Current {            get {                return _instance;            }        }  public IControllerFactory GetControllerFactory() {            return _serviceResolver.Current;        }        public void SetControllerFactory(IControllerFactory controllerFactory) {            if (controllerFactory == null) {                throw new ArgumentNullException("controllerFactory");            }            _factoryThunk = () => controllerFactory;        }        public void SetControllerFactory(Type controllerFactoryType) {            if (controllerFactoryType == null) {                throw new ArgumentNullException("controllerFactoryType");            }            if (!typeof(IControllerFactory).IsAssignableFrom(controllerFactoryType)) {                throw new ArgumentException(                    String.Format(                        CultureInfo.CurrentCulture,                        MvcResources.ControllerBuilder_MissingIControllerFactory,                        controllerFactoryType),                    "controllerFactoryType");            }            _factoryThunk = delegate() {                try {                    return (IControllerFactory)Activator.CreateInstance(controllerFactoryType);                }                catch (Exception ex) {                    throw new InvalidOperationException(                        String.Format(                            CultureInfo.CurrentCulture,                            MvcResources.ControllerBuilder_ErrorCreatingControllerFactory,                            controllerFactoryType),                        ex);                }            };        }
由以上代码我们可以知道如果没有调用ControllerBuilder的SetControllerFactory方法那我们就用默认的DefaultControllerFactory,如果设置了我们就可以用我们自己ControllerFactory。如果项目有需要实现自己的ControllerFactory,那么我们可以Global.asax.cs的 protected void Application_Start()方法调用 ControllerBuilder.Current.SetControllerFactory(xxx); 

让我们来看看DefaultControllerFactory是怎么创建的:

  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"
                );
            }
        }

这里我们涉及到一个IControllerActivator接口,默认情况下用的是DefaultControllerActivator类,

现在我们已经得到了ControllerFactory,再看看它是怎么创建Controller的,说白了就是DefaultControllerFactory的CreateController方法

 public virtual IController CreateController(RequestContext requestContext, string controllerName) {
    。。
            Type controllerType = GetControllerType(requestContext, controllerName);
            IController controller = GetControllerInstance(requestContext, controllerType);
            return controller;
        }

默认我们是没有namespaces,而GetControllerType(requestContext, controllerName)主要是调用 GetControllerTypeWithinNamespaces(requestContext.RouteData.Route, controllerName, null /* namespaces */)

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);                }            }        }
这里的_resolverThunk()来源于DependencyResolver.Current,
private static DependencyResolver _instance = new DependencyResolver();
        public static IDependencyResolver Current {
            get {
                return _instance.InnerCurrent;
            }
        }
 private IDependencyResolver _current = new DefaultDependencyResolver();
        public IDependencyResolver InnerCurrent {
            get {
                return _current;
            }
        }
所以真正创建controller是在DefaultDependencyResolver的GetService方法,核心代码   return Activator.CreateInstance(serviceType);
这篇文件扯得比较远,可见创建Controller是多么的麻烦啊。阅读源代码主要是让我们理解其逻辑,同时也让我们学习其开发的思想。
本文讲的这么多,在项目中最常用的就是ControllerBuilder.Current.SetControllerFactory(xxx);  只要大家理解了它就可以了。