这个 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)