前幾章已知 HttpApplication 初始化時會載入組態檔註冊的 HttpModule,但能否在初始化前動態載入?答案是肯定的。MVC 3 發布時隨附 Microsoft.Web.Infrastructure.dll,提供動態註冊功能。
[SecuritySafeCritical]
public static void RegisterModule(Type moduleType) {
if (DynamicModuleReflectionUtil.Fx45RegisterModuleDelegate != null) {
DynamicModuleReflectionUtil.Fx45RegisterModuleDelegate(moduleType);
} else {
LegacyModuleRegistrar.RegisterModule(moduleType);
}
}
.NET 4.5 直接使用 Helper,舊版透過 LegacyModuleRegistrar 以反射操作組態集合。以 IIS 6 經典模式為例:
private static void AddModuleToClassicPipeline(Type moduleType) {
HttpModulesSection httpModulesSection = null;
try {
object appConfig = _reflectionUtil.GetAppConfig();
httpModulesSection = _reflectionUtil.GetHttpModulesFromAppConfig(appConfig);
_reflectionUtil.SetConfigurationElementCollectionReadOnlyBit(httpModulesSection.Modules, false);
DynamicModuleRegistryEntry newEntry = CreateDynamicModuleRegistryEntry(moduleType);
httpModulesSection.Modules.Add(new HttpModuleAction(newEntry.Name, newEntry.Type));
} finally {
if (httpModulesSection != null) {
_reflectionUtil.SetConfigurationElementCollectionReadOnlyBit(httpModulesSection.Modules, true);
}
}
}
核心:從 RuntimeConfig.GetAppConfig().HttpModules 取得集合,移除唯讀旗標,新增 HttpModuleAction,再恢復唯讀。這必須在 HttpApplication 初始化所有模組之前完成。
HostingEnvironment.Initialize 中呼叫 BuildManager.CallPreStartInitMethods(),最終在 GetPreStartInitMethodsFromAssemblyCollection 掃描組件上的 PreApplicationStartMethodAttribute,執行對應靜態方法。此時機點早於 HttpApplication 建立,適合動態註冊模組。
此機制為 MVC、Web Pages 等框架提供無需修改 web.config 即可註冊模組的能力,是現代 ASP.NET 套件自動整合的基石。