通过前面的章节,我们知道HttpApplication在初始化的时候会初始化所有配置文件里注册的HttpModules,那么有一个疑问,能否初始化之前动态加载HttpModule,而不是只从Web.config里读取?
答案是肯定的, ASP.NET MVC3发布的时候提供了一个Microsoft.Web.Infrastructure.dll文件,这个文件就是提供了动态注册HttpModule的功能,那么它是如何以注册的呢?我们先去MVC3的源码看看该DLL的源代码。
注:该DLL位置在C:\Program Files\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\Assemblies\下
我们发现了一个静态类DynamicModuleUtility,里面有个RegisterModule方法引起了我的注意:
// Call from PreAppStart to dynamically register an IHttpModule, just as if you had added it to the // <modules> section in Web.config. [SecuritySafeCritical] public static void RegisterModule(Type moduleType) { if (DynamicModuleReflectionUtil.Fx45RegisterModuleDelegate != null) { // The Fx45 helper exists, so just call it directly. DynamicModuleReflectionUtil.Fx45RegisterModuleDelegate(moduleType); } else { // Use private reflection to perform the hookup. LegacyModuleRegistrar.RegisterModule(moduleType); } }
通过代码和注释我们可以看到,这个方法就是让我们动态注册IHttpModule的,而且由于.Net4.5已经有helper类支持了,所以直接就可以用,其它版本使用LegacyModuleRegistrar.RegisterModule来动态注册IHttpModule 的。而这个方法里又分IIS6和IIS7集成或经典模式之分,代码大体上是一致的,我们这里就只分析IIS6版本的代码:
private static void AddModuleToClassicPipeline(Type moduleType) { // This works by essentially adding a new entry to the <httpModules> section defined // in ~/Web.config. Need to set the collection to read+write while we do this. // httpModulesSection = RuntimeConfig.GetAppConfig().HttpModules; // httpModulesSection.Modules.bReadOnly = false; // httpModulesSection.Modules.Add(new HttpModuleAction(...)); // httpModulesSection.Modules.bReadOnly = true; HttpModulesSection httpModulesSection = null; try { object appConfig = _reflectionUtil.GetAppConfig(); httpModulesSection = _reflectionUtil.GetHttpModulesFromAppConfig(appConfig); _reflectionUtil.SetConfigurationElementCollectionReadOnlyBit(httpModulesSection.Modules, false /* value */); DynamicModuleRegistryEntry newEntry = CreateDynamicModuleRegistryEntry(moduleType); httpModulesSection.Modules.Add(new HttpModuleAction(newEntry.Name, newEntry.Type)); } finally { if (httpModulesSection != null) { _reflectionUtil.SetConfigurationElementCollectionReadOnlyBit(httpModulesSection.Modules, true /* value */); } } }
上面代码的注释非常重要,通过注释我们可以看到,该方法先从RuntimeConfig.GetAppConfig().HttpModules获取 HttpModules集合,然后在集合里添加需要注册的新HttpModule,那就是说HttpApplication在初始化所有 HttpModule之前必须将需要注册的HttpModule添加到这个集合里,那是在哪个周期呢?HttpApplication之前是 HostingEnvironment,那是不是在这里可以注册呢?我们去该类查看一下相关的代码,在Initialize方法里突然发现一个貌似很熟悉的代码BuildManager.CallPreStartInitMethods(),代码如下:
// call AppInitialize, unless the flag says not to do it (e.g. CBM scenario). // Also, don't call it if HostingInit failed (VSWhidbey 210495) if(!HttpRuntime.HostingInitFailed) { try { BuildManager.CallPreStartInitMethods(); if ((hostingFlags & HostingEnvironmentFlags.DontCallAppInitialize) == 0) { BuildManager.CallAppInitializeMethod(); } } catch (Exception e) { // could throw compilation errors in 'code' - report them with first http request HttpRuntime.InitializationException = e; if ((hostingFlags & HostingEnvironmentFlags.ThrowHostingInitErrors) != 0) { throw; } } }
通过去BuildManager类去查看该方法的详情,最终发现了如下这个方法:
internal static ICollection<MethodInfo> GetPreStartInitMethodsFromAssemblyCollection(IEnumerable<Assembly> assemblies) { List<MethodInfo> methods = new List<MethodInfo>(); foreach (Assembly assembly in assemblies) { PreApplicationStartMethodAttribute[] attributes = null; try { attributes = (PreApplicationStartMethodAttribute[])assembly.GetCustomAttributes(typeof(PreApplicationStartMethodAttribute), inherit: true); } catch { // GetCustomAttributes invokes the constructors of the attributes, so it is possible that they might throw unexpected exceptions. // (Dev10 bug 831981) } if (attributes != null && attributes.Length != 0) { Debug.Assert(attributes.Length == 1); PreApplicationStartMethodAttribute attribute = attributes[0]; Debug.Assert(attribute != null); MethodInfo method = null; // Ensure the Type on the attribute is in the same assembly as the attribute itself if (attribute.Type != null && !String.IsNullOrEmpty(attribute.MethodName) && attribute.Type.Assembly == assembly) { method = FindPreStartInitMethod(attribute.Type, attribute.MethodName); } if (method != null) { methods.Add(method); } else { throw new HttpException(SR.GetString(SR.Invalid_PreApplicationStartMethodAttribute_value, assembly.FullName, (attribute.Type != null ? attribute.Type.FullName : String.Empty), attribute.MethodName)); } } } return methods; }
本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/webkf/aspx/
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索代码
, null
, 注册
, attribute
, httpmodule
, HttpModules
Attributes
mvc httpmodule、springmvc 动态定时器、spring mvc 动态url、springmvc 动态数据源、springmvc动态国际化,以便于您获取更多的相关知识。