.Net MVC 里面的核心文件Global.asax运行原理分析

来源:互联网 发布:淘宝确认订单 编辑:程序博客网 时间:2024/06/05 19:48

这个 Global.asax文件是MVC里面的起始文件,它不同于其它文件比如,M层,V层和C层。他是一个独立的可配置的文件。

因为.Net MVC把前后端完全分离,极度抽象的一个框架。或许导致了很多从WebForm转过来的不适应。Global文件就是此类。

它与MVC里面的筛选器,控制器类工程(controllerFactory)的交互式怎么做大的呢?

实际上在System.Web命名空间里面,PipelineRunTime类的InitializeApplication方法会通过HttpApplicationFactory调用GetPipelineApplicationInstance方法创建Global.asax文件类。

 app(Global.asax) = HttpApplicationFactory.GetPipelineApplicationInstance(appContext, context); GetPipelineApplicationInstance调用如下: internal static HttpApplication GetPipelineApplicationInstance(IntPtr appContext, HttpContext context)    {        _theApplicationFactory.EnsureInited();        return _theApplicationFactory.GetSpecialApplicationInstance(appContext, context);    }

_theApplicationFactory 是一个全局静态类实例 private static HttpApplicationFactory _theApplicationFactory = new HttpApplicationFactory();实际上就是httpApplicationFactory类工场实例。

EnsureInited代码如下

 private void EnsureInited()    {        if (!this._inited)        {            HttpApplicationFactory factory = this;            lock (factory)            {                if (!this._inited)                {                    this.Init();                    this._inited = true;                }            }        }    }

Init代码如下:

  private void Init()    {        if (_customApplication == null)        {            try            {                try                {                    this._appFilename = GetApplicationFile();                    this.CompileApplication();                }                finally                {                    this.SetupChangesMonitor();                }            }            catch            {                throw;            }        }    }    

CompileApplication代码如下:

    private void CompileApplication()    {        this._theApplicationType = BuildManager.GetGlobalAsaxType();        BuildResultCompiledGlobalAsaxType globalAsaxBuildResult = BuildManager.GetGlobalAsaxBuildResult();        if (globalAsaxBuildResult != null)        {            if (globalAsaxBuildResult.HasAppOrSessionObjects)            {                this.GetAppStateByParsingGlobalAsax();            }            this._fileDependencies = globalAsaxBuildResult.VirtualPathDependencies;        }        if (this._state == null)        {            this._state = new HttpApplicationState();        }        this.ReflectOnApplicationType();    }

ReflectOnApplicationType代码如下:

    private void ReflectOnApplicationType()    {        ArrayList list = new ArrayList();        foreach (MethodInfo info in this._theApplicationType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance))        {            if (this.ReflectOnMethodInfoIfItLooksLikeEventHandler(info))            {                list.Add(info);            }        }        Type baseType = this._theApplicationType.BaseType;        if ((baseType != null) && (baseType != typeof(HttpApplication)))        {            foreach (MethodInfo info2 in baseType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))            {                if (info2.IsPrivate && this.ReflectOnMethodInfoIfItLooksLikeEventHandler(info2))                {                    list.Add(info2);                }            }        }        this._eventHandlerMethods = new MethodInfo[list.Count];        for (int i = 0; i < this._eventHandlerMethods.Length; i++)        {            this._eventHandlerMethods[i] = (MethodInfo) list[i];        }    }

ReflectOnMethodInfoIfItLooksLikeEventHandler代码如下:

   private bool ReflectOnMethodInfoIfItLooksLikeEventHandler(MethodInfo m)    {        if (m.ReturnType != typeof(void))        {            return false;        }        ParameterInfo[] parameters = m.GetParameters();        int length = parameters.Length;        if (length != 0)        {            if (length != 2)            {                return false;            }            if (parameters[0].ParameterType != typeof(object))            {                return false;            }            if ((parameters[1].ParameterType != typeof(EventArgs)) && !parameters[1].ParameterType.IsSubclassOf(typeof(EventArgs)))            {                return false;            }        }        string name = m.Name;        int index = name.IndexOf('_');        if ((index <= 0) || (index > (name.Length - 1)))        {            return false;        }        if (StringUtil.EqualsIgnoreCase(name, "Application_OnStart") || StringUtil.EqualsIgnoreCase(name, "Application_Start"))        {            this._onStartMethod = m;            this._onStartParamCount = parameters.Length;        }        else if (StringUtil.EqualsIgnoreCase(name, "Application_OnEnd") || StringUtil.EqualsIgnoreCase(name, "Application_End"))        {            this._onEndMethod = m;            this._onEndParamCount = parameters.Length;        }        else if (StringUtil.EqualsIgnoreCase(name, "Session_OnEnd") || StringUtil.EqualsIgnoreCase(name, "Session_End"))        {            this._sessionOnEndMethod = m;            this._sessionOnEndParamCount = parameters.Length;        }        return true;    }

ReflectOnMethodInfoIfItLooksLikeEventHandler里面获取到了当前Global.asax方法Application_OnStart

再来看GetPipelineApplicationInstance方法里面调用的第二个方法GetSpecialApplicationInstance。它里面会调用 application = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);创建HtppApplication ,实际上就是Global.asax里面的类MvcApplication。它会调用ProcessSpecialRequest方法反射上面得到的HttpApplication里面的方法Application_start,最后用Invoke调用。

  this.InvokeMethodWithAssert(method, paramCount, eventSource, eventArgs);  [ReflectionPermission(SecurityAction.Assert, Flags=ReflectionPermissionFlag.RestrictedMemberAccess)]    private void InvokeMethodWithAssert(MethodInfo method, int paramCount, object eventSource, EventArgs eventArgs)    {        if (paramCount == 0)        {            method.Invoke(this, new object[0]);        }        else        {            object[] parameters = new object[] { eventSource, eventArgs };            method.Invoke(this, parameters);        }    }

最后进入到Application_start()里面调用MVC的一些前奏,比如配置全局筛选器,创建路由表,注册Area等等。

值得注意的是,这一系列事件都在 进入HTTPModule和HttpHandler之前发生,所以后面等到激活Controller调用ControllerFactory和筛选器递归链的时候,Application_start里面的配置都会起作用。

还有一点需要注意的是,这个Application_start只会在第一次请求加载,后续陆续请求不会再次加载。如果需要重新加载,关掉程序,重新来过,则又会运行到Application_start方法里面。

原创粉丝点击