zoukankan      html  css  js  c++  java
  • Orchard源码分析(2):Orchard.Web.MvcApplication类(Global)

    概述
    分析一个的ASP.NET项目源码,首先可以浏览其项目结构,大致一窥项目其全貌,了解项目之间的依赖关系。其次可以浏览Web.configGlobal.asax文件,找到应用程序的入口点。
    本 文主要分析Orchard项目的Global.asax文件,而真正的分析入口点在Global.asax的CodeBehind文件 Global.asax.cs中,即Orchard.Web.MvcApplication类(以下简称MvcApplication类)。
     
    MvcApplication类处理了三个事件Start,BeginRequest和EndRequest。其中是否真有名为"Start"的事件还不明确,这里暂且这么简单的理解。
    根 据约定,这三个事件分别对应Application_Start、Application_BeginRequest和 Application_EndRequest事件处理程序(方法),当然也可以通过重写HttpApplication的Init方法注册其他名称的事 件处理程序——Application_Start除外。
     
    Start是个特殊事件,仅在请求 ASP.NET 应用程序中第一个资源(如aspx页)时调用。在该事件的处理程序(Application_Start方法)中,可用于也应该仅用于在应用程序启动期间设置静态共享数据。Orchard中主要用于配置Autofac容器、安装扩展(Modules和Themes统称为扩展)、创建并激活Shell(子站点)。
    BeginRequest事件在 ASP.NET 响应请求时作为 HTTP 执行管线链(管道)中的第一个事件发生。Orchard中主要用户监视扩展;如果扩展发生改变会重新安装扩展、重新创建并激活Shell;如果Shell状态等也发生改变会重新激活Shell。
    EndRequest事件在 ASP.NET 响应请求时作为 HTTP 执行管线链中的最后一个事件发生。Orchard中主要用于处理完"处理引擎(ProcessingEngine)"中的任务(Task)。
     
    一、Application_Start方法
    下面的代码分析要在MvcApplication类和Orchard.WarmupStarter.Starter<T>类(以下简称Starter<T>类)之间切换。
    Application_Start方法首先调用了RegisterRoutes方法,添加了一个路由配置,将对后缀为".axd"的请求排除在ASP.NET MVC处理管道之外。这里将方法内联后看:
        RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}" );
    接着Application_Start方法中使用泛型类型参数IOrchardHost,调用Starter<T>类带三个委托参数的构造函数创建其实例并赋给了静态私有字段_starter:
        _starter = new Starter<IOrchardHost >(HostInitialization, HostBeginRequest, HostEndRequest);
    其中静态私有字段_starter定义在MvcApplication类中有定义:
        private static StarterIOrchardHost> _starter;
    另暂且不管IOrchardHost的定义及其作用,这里只需要知道Starter<T>类有责任创建一个IOrchardHost(DefaultOrchardHost)实例。
    Starter<T> 类构造函数接受三个委托参数。在创建该类型的对象时,传入HstInitialization、HostBeginRequest和 HostEndRequest的三个参数是在MvcApplication类中定义的三个私有静态方法(当然,会被包装成委托):
        IOrchardHost HostInitialization(HttpApplication application)
        void HostBeginRequest(HttpApplication application, IOrchardHost host)
        void HostEndRequest(HttpApplication application, IOrchardHost host)
     
    下面转入Starter<T>类看其构造函数的定义:
             public Starter(Func <HttpApplication, T> initialization, Action<HttpApplication , T> beginRequest, Action<HttpApplication , T> endRequest) {
                _initialization = initialization;
                _beginRequest = beginRequest;
                _endRequest = endRequest;
                }
     
    可见该构造函数内部只是简单的赋值操作,将参数值赋给Starter<T>类内部对应的私有的委托类型字段。
     
    再转回Application_Start方法继续分析。
    Application_Start方法接着调用_starter的OnApplicationStart方法,将当前的MvcHttpApplication实例作为参数传入:
        _starter.OnApplicationStart( this);
    深 入Starter<T>.OnApplicationStart方法内部,该方法通过线程池启动一个线程。新线程中最终会调用 MvcHttpApplication类中的HostInitialization方法——即作为参数传给Starter<T>构造函数的委 托所包装的方法。具体分析请参考下一篇关于Orchard.WarmupStarter程序集的分析。这里再看看HostInitialization方 法的定义:      
        private static IOrchardHost HostInitialization( HttpApplication application) {
            var host = OrchardStarter .CreateHost(MvcSingletons);
     
            host.Initialize();
     
            // initialize shells to speed up the first dynamic query
            host.BeginRequest();
            host.EndRequest();
     
             return host;
        }
    该方法目的是创建一个IOrchardHost(DefaultOrchardHost)对象并调用其几个方法,然后将其返回。这里暂不深究IOrchardHost这几个方法的作用。
     
    二、Application_BeginRequest方法和Application_EndRequest方法
    这两个方法比较简单,只是简单调用Starter<T>类的对应方法:
         protected void Application_BeginRequest() {
            _starter.OnBeginRequest( this);
        }
     
        protected void Application_EndRequest() {
            _starter.OnEndRequest( this);
        }
     
    Starter<T>的OnBeginRequest和OnEndRequest方法会调用MvcApplication的HostBeginRequest和HostEndRequest方法:
        public void OnBeginRequest(HttpApplication application)
        {
            // ... (省略的代码请查看Starter<T>类,在下一篇中将会进行分析)
            // Only notify if the initialization has successfully completed
            if (_initializationResult != null )
            {
                _beginRequest(application, _initializationResult);
            }
        }
     
        public void OnEndRequest(HttpApplication application)
        {
            // Only notify if the initialization has successfully completed
            if (_initializationResult != null )
            {
                _endRequest(application, _initializationResult);
            }
        }
    HostBeginRequest和HostEndRequest方法最终会转到对IOrchardHost(DefaultOrchardHost)对应方法的调用:
        private static void HostBeginRequest( HttpApplication application, IOrchardHost host) {
            application.Context.Items[ "originalHttpContext"] = application.Context;
            host.BeginRequest();
        }
     
        private static void HostEndRequest( HttpApplication application, IOrchardHost host) {
            host.EndRequest();
        }
    注意,HostBeginRequest方法将当前请求上下文(HttpContext)保存在会话状态(HttpContext.Items)中。
     
    从 上面不难看出,一项交由MvcApplication来完成的工作,它推给了Starter<T>,后者完成一部分后又转给 MvcApplication处理,MvcApplication接着处理一部分后,把剩下的工作全交给 IOrchardHost(DefaultOrchardHost)来完成。
     
    在分析Orchard.WarmupStarter程序集的时候将详细分析Starter<T>类。对IOrchardHost(DefaultOrchardHost)也有专门的篇幅来分析。
    三、疑问
    对MvcHttpApplication分析暂时就到这里,它虽然就短短60多行代码,而且包括注释。但留给我们的疑问倒却不少:
    1、上面虽然数次提到IOrchardHost(DefaultOrchardHost),但它到底是什么,它的作用又是什么?
    2、MvcApplication.HostInitialization方法中,调用OrchardStarter.CreateHost方法创建IOrchardHost实例的,它是如何创建的?
    3、MvcApplication.HostInitialization方法中,调用IOrchardHost.Initialize方法后,为什么还要调用IOrchardHost.BeginRequest和IOrchardHost.EndRequest方法?
    4、为什么要在MvcApplication.HostBeginRequest方法中将当前请求上下文(HttpContext)保存在会话状态(HttpContext.Items)中?
    5、Orchard.WarmupStarter程序集是做什么用的?
    6、Starter<T>在把任务传回MvcApplication之前,完成了那些工作?
    7、MvcApplication.MvcSingletons方法涉及到IoC/DI,Autofac是如何工作的?

    相关类型:
    Orchard.WarmupStarter.Starter<T>
    Orchard.Environment.DefaultOrchardHost : Orchard.Environment.IOrchartHost
    Orchard.Environment.OrchardStarter
     
    参考资料:

    HttpApplication的认识与加深理解

  • 相关阅读:
    杭电dp题集,附链接还有解题报告!!!!!
    js正則表達式语法
    java界面编程(8) ------ 组合框(下拉列表)
    四个好看的CSS样式表格
    搜集朋友写的几篇Android Elf相关的文档
    hadoop编程小技巧(5)---自己定义输入文件格式类InputFormat
    递归算法
    ua识别(浏览器标识识别)
    amazeui学习笔记一(开始使用5)--藏品collections
    amazeui学习笔记一(开始使用4)--Web App 相关
  • 原文地址:https://www.cnblogs.com/Alex80/p/5217045.html
Copyright © 2011-2022 走看看