这是一个非常有趣的问题。我花了一段时间才了解 Asp.Net 引导管道。我不会详细介绍,因为这会花费很多,所以我将把细节留给 OP。
基本上,Asp.Net 框架会动态创建一个程序集并创建一个动态创建的类型,该类型继承您的MvcApplication。
所以这里是默认的MvcApplication
public class MvcApplication : HttpApplication {
public static void Application_Start() {
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
那么,Asp.Net 框架动态创建另一个程序集和类型是什么意思?您会注意到通过检查以下代码→
让我们修改Application_Start方法:
public static void Application_Start() {
var whatIsMyType = GetType();
//You will see that our actual type is of ASP.global_asax,
//which inherits MvcApplication, which inherits HttpApplication
//Other Stuff...
}
ASP.global_asax 类型是在哪里创建的?你需要深入挖掘源代码,但让我给你一个hint
那么实际的 ASP.global_asax 是什么样子的呢?
[System.Runtime.CompilerServices.CompilerGlobalScopeAttribute()]
public class global_asax : global::<YourNameSpace>.MvcApplication {
private static bool @__initialized;
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global_asax() {
if ((global::ASP.global_asax.@__initialized == false)) {
global::ASP.global_asax.@__initialized = true;
}
}
protected System.Web.Profile.DefaultProfile Profile {
get {
return ((System.Web.Profile.DefaultProfile)(this.Context.Profile));
}
}
}
最后,我们可以进入实际的答案:为什么将Application_Start 设为静态会使应用程序以意想不到的方式运行?
在用于引导应用程序的HttpApplicationFactory 类中,有以下代码行
methods = _theApplicationType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
foreach (MethodInfo m in methods) {
if (ReflectOnMethodInfoIfItLooksLikeEventHandler(m))
handlers.Add(m);
}
谜题在_theApplicationType 解决。请记住这是ASP.global_asax type。您的静态方法Application_Start 定义在MvcApplication 类型中,因此反射不会通过_theApplicationType 找到它,因此它不会被分配为在应用程序启动时调用。
这是一个简单的检查代码。
public class BaseClass {
public static void StaticMethodInBaseClass() {
}
}
public class DerivedClass {
public void DerivedClassMethod() {
}
}
//You will not get `StaticMethodInBaseClass` here
var methods = typeof(DerivedClass).GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);