[MVC]ASP.NET MVC Preview 3 流程分析 - 1. MvcHandler

baacloud免费翻墙vpn注册使用

1. 这次的旅程将从 MvcRouteHandler 开始。(有源码,分析起来就是方便~~~~ 调整一下,直接在源码设断点)

System.Web.Mvc.DLL!System.Web.Mvc.MvcRouteHandler.System.Web.Routing.IRouteHandler.GetHttpHandler(…
System.Web.Routing.DLL!System.Web.Routing.UrlRoutingModule.PostResolveRequestCache(…
System.Web.Routing.DLL!System.Web.Routing.UrlRoutingModule.OnApplicationPostResolveRequestCache(…
System.Web.dll!System.Web.HttpApplication…..System.Web.HttpApplication.IExecutionStep.Execute(…
System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step…
System.Web.dll!System.Web.HttpApplication.ApplicationStepManager.ResumeSteps(…
System.Web.dll!System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(…
System.Web.dll!System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest wr…
System.Web.dll!System.Web.HttpRuntime.ProcessRequestNoDemand(…
System.Web.dll!System.Web.HttpRuntime.ProcessRequest(…


上面是起始调用堆栈,我们会发现 UrlRoutingModule 通过调用 MvcRouteHandler.GetHttpHandler() 引发本次追逃行动。

public class MvcRouteHandler : IRouteHandler
{
  protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
  {
    return new MvcHandler(requestContext);
  }


生成一个 MvcHandler 对象,同时将请求上下文传递过去。接下来的事情自然交给这个 IHttpHandler 了。
2. MvcHandler.ProcessRequest 被系统调用。

public class MvcHandler : IHttpHandler, IRequiresSessionState
{
  void IHttpHandler.ProcessRequest(HttpContext httpContext)
  {
    ProcessRequest(httpContext);
  }
  protected virtual void ProcessRequest(HttpContext httpContext)
  {
    HttpContextBase iHttpContext = new HttpContextWrapper(httpContext);
    ProcessRequest(iHttpContext);
  }


创建一个新的上下文包装器 —— HttpContextWrapper,这里面有大量的属性和方法方便我们获取相关环境及请求上下文信息。

public class HttpContextWrapper : HttpContextBase
{
  public HttpContextWrapper(HttpContext httpContext);
  public override Exception[] AllErrors { get; }
  public override HttpApplicationStateBase Application { get; }
  public override HttpApplication ApplicationInstance { get; set; }
  public override Cache Cache { get; }
  public override IHttpHandler CurrentHandler { get; }
  public override RequestNotification CurrentNotification { get; }
  public override Exception Error { get; }
  public override IHttpHandler Handler { get; set; }
  public override bool IsCustomErrorEnabled { get; }
  public override bool IsDebuggingEnabled { get; }
  public override bool IsPostNotification { get; }
  public override IDictionary Items { get; }
  public override IHttpHandler PreviousHandler { get; }
  public override ProfileBase Profile { get; }
  public override HttpRequestBase Request { get; }
  public override HttpResponseBase Response { get; }
  public override HttpServerUtilityBase Server { get; }
  public override HttpSessionStateBase Session { get; }
  public override bool SkipAuthorization { get; set; }
  public override DateTime Timestamp { get; }
  public override TraceContext Trace { get; }
  public override IPrincipal User { get; set; }
  public override void AddError(Exception errorInfo);
  public override void ClearError();
  // … 省略部分代码 …
}


回到 MvcHandler 的执行流程。

protected internal virtual void ProcessRequest(HttpContextBase httpContext)
{
  // Get the controller type
  string controllerName = RequestContext.RouteData.GetRequiredString("controller");
  // Instantiate the controller and call Execute
  IControllerFactory factory = ControllerBuilder.GetControllerFactory();
  IController controller = factory.CreateController(RequestContext, controllerName);
  // … 省略部分代码 …
  try
  {
    ControllerContext controllerContext = new ControllerContext(RequestContext, controller);
    controller.Execute(controllerContext);
  }
  finally
  {
    factory.DisposeController(controller);
  }
}


从上下文的 Route 字典里查找 Controller 的类型名称(Type Name),然后交由 ControllerFactory 创建控制器对象实例。控制器的执行(Execute)和清理(DisposeController)我们放到下一篇,现在的任务是看看 ControllerBuilder 都做了些什么?

public class MvcHandler : IHttpHandler, IRequiresSessionState
{
  internal ControllerBuilder ControllerBuilder
  {
    get
    {
      if (_controllerBuilder == null)
      {
        _controllerBuilder = ControllerBuilder.Current;
      }
      return _controllerBuilder;
    }
    set
    {
      _controllerBuilder = value;
    }
  }
}


有个默认实例,进去看看。

public class ControllerBuilder
{
  private static ControllerBuilder _instance = new ControllerBuilder();
  private Func<IControllerFactory> _factoryThunk;
  public ControllerBuilder()
  {
    SetControllerFactory(new DefaultControllerFactory());
 }
  public static ControllerBuilder Current
  {
    get { return _instance; }
  }


很简单,不是吗?在构造方法里面我们看到了 Factory。

public void SetControllerFactory(IControllerFactory controllerFactory)
{
  if (controllerFactory == null)
  {
    throw new ArgumentNullException("controllerFactory");
  }
  _factoryThunk = () => controllerFactory;
}


创建 _factoryThunk 委托,返回构造方法中创建的 DefaultControllerFactory 对象。还有另外一个 SetControllerFactory 重载方法,基本意思差不多,只不过反射 Type 来创建 IControllerFactory 实例而已。
MvcHandler.ProcessRequest() 里面的调用的 GetControllerFactory() 方法又干了些什么呢?

public IControllerFactory GetControllerFactory()
{
  IControllerFactory controllerFactoryInstance = _factoryThunk();
  return controllerFactoryInstance;
}


我晕~~~~ 其实拐来拐去还是返回构造里面那个 DefaultControllerFactory 实例。
接下来 MvcHandler.ProcessRequest() 里面会调用 "factory.CreateController(RequestContext, controllerName)" 来创建控制器。这次去 DefaultControllerFactory 它们家溜达溜达。
内部对控制器相关信息做了缓存以提高系统效率。

public class DefaultControllerFactory : IControllerFactory
{
  protected internal virtual IController CreateController(…)
  {
    // … 省略部分代码 …
    RequestContext = requestContext;
    Type controllerType = GetControllerType(controllerName);
    IController controller = GetControllerInstance(controllerType);
    return controller;
 }
  protected internal virtual Type GetControllerType(string controllerName)
  {
    // … 省略部分代码 …
    // 检查缓存标记,利用反射将未缓存的相关控制器类型添加到缓存
    if (!ControllerTypeCache.Initialized)
    {
      // … 省略部分代码 …
    }
    // Once the master list of controllers has been created we can quickly index into it
    Type controllerType;
    // 用控制器名称从缓存中提取控制器类型,为空则抛出异常。
    if (ControllerTypeCache.TryGetControllerType(controllerName, out controllerType))
    {
      if (controllerType == null)
      {
        // A null value indicates a conflict for this key (i.e. more than one match)
        throw new InvalidOperationException(
          String.Format(
            CultureInfo.CurrentUICulture,
            MvcResources.DefaultControllerFactory_DuplicateControllers,
            controllerName));
      }
      return controllerType;
    }
    return null;
  }
  protected internal virtual IController GetControllerInstance(Type controllerType)
  {
    // … 省略部分代码 …
    try
    {
      return Activator.CreateInstance(controllerType) as IController;
    }
    catch (Exception ex)
    {
      // … 省略部分代码 …
    }
  }


整个过程很简单,利用传递进来的控制器类型名称参数,反射查找相应的类型(Type)信息,然后交由 Activator.CreateInstance 创建控制器对象实例。
流程分析图

 

点击看大图

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏