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

这个 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方法里面。(Java/.NET讨论群:676817308)

你可能感兴趣的:(凤)