<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      MVC之前的那點事兒系列(6):動態注冊HttpModule

      2014-06-05 08:58  湯姆大叔  閱讀(10278)  評論(10)    收藏  舉報

      文章內容

      通過前面的章節,我們知道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; 
      } 

      發現了該方法會查找應用程序下所有的程序集,判斷如果程序集標記為PreApplicationStartMethodAttribute特性,就會執行這個特性里指定的方法(靜態方法),再檢查該類的代碼:

          [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)] 
          public sealed class PreApplicationStartMethodAttribute : Attribute {
               private readonly Type _type;
              private readonly string _methodName;
              public PreApplicationStartMethodAttribute(Type type, string methodName) { 
                  _type = type;
                  _methodName = methodName; 
              } 
      
              public Type Type {   get { return _type; }   } 
              public string MethodName {  get {  return _methodName; }   }
          }

      這時候,心里應該有數了吧,我們可以在這里指定一個靜態方法名稱,然后在該方法去通過如下代碼去注冊一個自定義的HttpModule(注意我們只能使用一次):

      DynamicModuleUtility.RegisterModule(typeof(CustomModule));

      我們來做個試驗試試我們分析的結果是不是正確,首先創建一個自定義HttpModule,代碼如下:

      public class CustomModule : IHttpModule
      {
          public void Init(HttpApplication context)
          {
              context.BeginRequest += new EventHandler(context_BeginRequest);
                  
          }
      
          void context_BeginRequest(object sender, EventArgs e)
          {
              HttpApplication ap = sender as HttpApplication;
              if (ap != null)
              {
                  ap.Response.Write("湯姆大叔測試PreApplicationStartMethod通過!<br/>");
              }
          }
      
          public void Dispose()
          {
              //nothing to do here
          }
      }

      然后在創建一個用于注冊這個HttpModule的類并且帶有靜態方法:

      public class PreApplicationStartCode
      {
          private static bool hasLoaded;
      
          public static void PreStart()
          {
              if (!hasLoaded)
              {
                  hasLoaded = true;
                  //注意這里的動態注冊,此靜態方法在Microsoft.Web.Infrastructure.DynamicModuleHelper
                  DynamicModuleUtility.RegisterModule(typeof(CustomModule));
              }
          }
      }

      接著要安裝要求對該程序添加一個特性,代碼如下:

      [assembly: PreApplicationStartMethod(typeof(WebApplication1.Test.PreApplicationStartCode), "PreStart")]

      最后,編譯運行,會發現所有的頁面頂部都會出現我們指定的文字(湯姆大叔測試PreApplicationStartMethod通過!),截圖如下:

      這就證實了我們的分析結果是正確的,怎么樣,這個功能不錯吧,不需要每次都在web.config里定義你的HttpModule咯,而且我們以后封裝自己的類庫就方便多了,不需要在網站程序集里指定代碼去啟動自己封裝好的單獨類庫了,因為我們可以在自己的類庫里直接使用這種方式實現自動注冊的功能。下個章節,我們將介紹一個利用此功能開發的超強類庫。

      注:同一個程序集只能使用一次這個特性來調用一個靜態方法。

      同步與推薦

      本文已同步至目錄索引:MVC之前的那點事兒系列

      MVC之前的那點事兒系列文章,包括了原創,翻譯,轉載等各類型的文章,如果對你有用,請推薦支持一把,給大叔寫作的動力。

      主站蜘蛛池模板: 中文有无人妻vs无码人妻激烈| 韩国美女福利视频一区二区| 中文午夜乱理片无码| 99久久精品久久久久久婷婷 | 成人午夜在线观看日韩| 肃宁县| 亚洲精品三区二区一区一| 九九热精品视频免费在线| 做暖暖视频在线看片免费| 玩弄放荡人妻少妇系列| 乱女乱妇熟女熟妇综合网| 中文字幕人妻在线精品| 毛片无码免费无码播放| 少妇伦子伦精品无吗| 国产一区二区不卡在线视频| 国产成人高清亚洲综合| 国产农村激情免费专区| 国产成年码av片在线观看| 中文字幕乱码一区二区免费| 日韩精品亚洲精品第一页| 婷婷99视频精品全部在线观看 | 欧美一本大道香蕉综合视频| 一本久道中文无码字幕av| 欧美大胆老熟妇乱子伦视频| 好深好湿好硬顶到了好爽| 中国少妇人妻xxxxx| 国产欧美日韩视频怡春院| 依依成人精品视频在线观看| 天堂资源在线| 高清色本在线www| 重口SM一区二区三区视频| 神马久久亚洲一区 二区| 毛片免费观看视频| 国产线播放免费人成视频播放| 狠狠综合久久av一区二| 亚洲欧美成人久久综合中文网| 97欧美精品系列一区二区| 亚洲性一交一乱一伦视频| 日本精品极品视频在线| 日本污视频在线观看| 激情人妻自拍中文夜夜嗨|