日期:2014-05-17  浏览次数:20964 次

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"