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

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

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

      MVC之前的那點事兒系列(7):WebActivator的實現原理詳解

      2014-06-06 08:46  湯姆大叔  閱讀(11306)  評論(3)    收藏  舉報

      文章內容

      上篇文章,我們分析如何動態注冊HttpModule的實現,本篇我們來分析一下通過上篇代碼原理實現的WebActivator類庫,WebActivator提供了3種功能,允許我們分別在HttpApplication初始化之前,之后以及ShutDown的時候分別執行指定的代碼,示例如下:

      [assembly: WebActivator.PreApplicationStartMethod(typeof(A.InitClass1), "PreStart")]
      [assembly: WebActivator.PostApplicationStartMethod(typeof(A.InitClass1), "PostStart")]
      [assembly: WebActivator.ApplicationShutdownMethod(typeof(A.InitClass1), "ShutDown")]

      另外還有一點和系統自帶的PreApplicationStartMethodAttribute不同的是,WebActivator的每種特性都可以使用多次,比如:

      [assembly: WebActivator.PreApplicationStartMethod(typeof(A.InitClass1), "PreStart")]
      [assembly: WebActivator.PreApplicationStartMethod(typeof(A.InitClass2), "PreStart")]
      [assembly: WebActivator.PreApplicationStartMethod(typeof(A.InitClass3), "PreStart")]

      因為它的源碼很少,所以今天我們就來全面分析一下WebActivator的實現原理,首先下載WebActivator的最新1.5源碼,源碼地址:https://bitbucket.org/davidebbo/webactivator/src

       

      解壓代碼,我們可以看到WebActivator項目里總共有6個重要的cs文件,以及一個packages.config文件(用于標記本項目引用了Microsoft.Web.Infrastructure.dll類庫),下面我們來分析一下每個文件的源碼。

       

      3個XXXMethodAttribute屬性:

      根據上面的用法,我們指導WebActivator提供了3個MethodAttribute,我們先來看看這3個文件都是如何實現的,查閱代碼發現3個類(PreApplicationStartMethodAttribute/ PostApplicationStartMethodAttribute/ ApplicationShutdownMethodAttribute)的內容都是一樣的,都是繼承于BaseActivationMethodAttribute類,然后提供構造函數所需要的Type類型和方法名稱, 3個特性類都支持使用多次并且只能用于Assembly,代碼如下:

      [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]

      通用的基類BaseActivationMethodAttribute:

      using System;
      using System.Reflection;
      
      namespace WebActivator
      {
          // Base class of all the activation attributes
          [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
          public abstract class BaseActivationMethodAttribute : Attribute
          {
              private Type _type;
              private string _methodName;
      
              public BaseActivationMethodAttribute(Type type, string methodName)
              {
                  _type = type;
                  _methodName = methodName;
              }
      
              public Type Type { get { return _type; } }
      
              public string MethodName { get { return _methodName; } }
      
              public int Order { get; set; }
      
      
              public void InvokeMethod()
              {
                  // Get the method
                  MethodInfo method = Type.GetMethod(
                      MethodName,
                      BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
      
                  if (method == null)
                  {
                      throw new ArgumentException(
                          String.Format("The type {0} doesn't have a static method named {1}",
                              Type, MethodName));
                  }
      
                  // Invoke it
                  method.Invoke(null, null);
              }
          }
      }

      通過代碼,我們首先可以看到,除了Type和MethodName以外,還多了一個Order屬性,用來標記多次使用同一個Attribute的時候的執行順序。然后提供了一個InvokeMethod方法,用來執行該類里傳入當前Type類的MethodName靜態方法。

       

      Assembly擴展方法AssemblyExtensions:

      using System.Collections.Generic;
      using System.Linq;
      using System.Reflection;
      
      namespace WebActivator
      {
          static class AssemblyExtensions
          {
              // Return all the attributes of a given type from an assembly
              public static IEnumerable<T> GetActivationAttributes<T>(this Assembly assembly) where T : BaseActivationMethodAttribute
              {
                  return assembly.GetCustomAttributes(
                      typeof(T),
                      inherit: false).OfType<T>();
              }
          }
      }

      該擴展方法主要是用于獲取某一個程序集Assembly下指定類型的所有Attribute(并且不包括繼承的類),也就是查詢上述3種特性的Attributes(因為每種都允許聲明多次)。

       

      主管理類ActivationManager:

      該類主要分為如下幾個部分:

      1 私有靜態函數Assemblies, GetAssemblyFiles主要是獲取當前應用程序下的所有DLL程序集,以供其它方法從這個程序集集合里遍歷相應的特性聲明。

      // 加載所有獲取的程序集
      private static IEnumerable<Assembly> Assemblies
      {
          get
          {
              if (_assemblies == null)
              {
                  // Cache the list of relevant assemblies, since we need it for both Pre and Post
                  _assemblies = new List<Assembly>();
                  foreach (var assemblyFile in GetAssemblyFiles())
                  {
                      try
                      {
                          // Ignore assemblies we can't load. They could be native, etc...
                          _assemblies.Add(Assembly.LoadFrom(assemblyFile));
                      }
                      catch
                      {
                      }
                  }
              }
      
              return _assemblies;
          }
      }
      
      // 獲取程序集文件路徑集合
      private static IEnumerable<string> GetAssemblyFiles()
      {
          // When running under ASP.NET, find assemblies in the bin folder.
          // Outside of ASP.NET, use whatever folder WebActivator itself is in
          string directory = HostingEnvironment.IsHosted
              ? HttpRuntime.BinDirectory
              : Path.GetDirectoryName(typeof(ActivationManager).Assembly.Location);
          return Directory.GetFiles(directory, "*.dll");
      }

      2 獲取所有AppCode文件夾下代碼編譯后的程序集。

      // Return all the App_Code assemblies
      private static IEnumerable<Assembly> AppCodeAssemblies
      {
          get
          {
              // Return an empty list if we;re not hosted or there aren't any
              if (!HostingEnvironment.IsHosted || !_hasInited || BuildManager.CodeAssemblies == null)
              {
                  return Enumerable.Empty<Assembly>();
              }
      
              return BuildManager.CodeAssemblies.OfType<Assembly>();
          }
      }

      3 執行3種特性里所指定的方法

      public static void RunPreStartMethods()
      {
          RunActivationMethods<PreApplicationStartMethodAttribute>();
      }
      
      public static void RunPostStartMethods()
      {
          RunActivationMethods<PostApplicationStartMethodAttribute>();
      }
      
      public static void RunShutdownMethods()
      {
          RunActivationMethods<ApplicationShutdownMethodAttribute>();
      }
      
      // Call the relevant activation method from all assemblies
      private static void RunActivationMethods<T>() where T : BaseActivationMethodAttribute
      {
          foreach (var assembly in Assemblies.Concat(AppCodeAssemblies))
          {
              foreach (BaseActivationMethodAttribute activationAttrib in assembly.GetActivationAttributes<T>().OrderBy(att => att.Order))
              {
                  activationAttrib.InvokeMethod();
              }
          }
      }

      從代碼可以看出,3個特性執行方法調用的都是同一個泛型方法RunActivationMethods<T>,在這個方法里,主要是從所有的程序集里,通過泛型方法查詢所有標記的特性(按Order排序),并且執行每個特性聲明里指定的方法。另外從Assemblies.Concat(AppCodeAssemblies)可以發現,所有的程序集還要包括App_Code目錄下代碼編譯的程序集哦。

       

      4 自定義HttpModule

      class StartMethodCallingModule : IHttpModule
      {
          private static object _lock = new object();
          private static int _initializedModuleCount;
      
          public void Init(HttpApplication context)
          {
              lock (_lock)
              {
                  // Keep track of the number of modules initialized and
                  // make sure we only call the post start methods once per app domain
                  if (_initializedModuleCount++ == 0)
                  {
                      RunPostStartMethods();
                  }
              }
          }
      
          public void Dispose()
          {
              lock (_lock)
              {
                  // Call the shutdown methods when the last module is disposed
                  if (--_initializedModuleCount == 0)
                  {
                      RunShutdownMethods();
                  }
              }
          }
      }

      該Module主要是用于在 Init的時候執行PostStart類型的方法,并且在Dispose的時候執行Shutdown類型的方法,并且只執行一次。

       

      5.最重要的入口方法

      public static void Run()
      {
          if (!_hasInited)
          {
              RunPreStartMethods();
      
              // Register our module to handle any Post Start methods. But outside of ASP.NET, just run them now
              if (HostingEnvironment.IsHosted)
              {
                  Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(StartMethodCallingModule));
              }
              else
              {
                  RunPostStartMethods();
              }
      
              _hasInited = true;
          }
      }

      Run方法看起來很容易理解了,首先執行PreStart類型的方法,然后判斷HostingEnvironment是否Host成功,如果成功就動態注冊我們上面自定義的HttpModule,以便讓該Module在HttpApplication初始化和Dispose的時候分別執行PostStart類型的方法和ShutDown類型的方法,如果沒有Host成功,那只執行PostStart類型的方法。

      注:由代碼實現可以看出,在PreStart類型的方法里,不能使用HttpContext對象進行輸入輸出,因為該對象在此時還沒用創建成功呢。

       

      6.誰調用了入口方法Run()

      這個就不用多說了吧,肯定是使用.Net4.0自帶的PreApplicationStartMethodAttribute特性,代碼如下:

      [assembly: PreApplicationStartMethod(typeof(WebActivator.ActivationManager), "Run")]

      你可以讓這段代碼放在WebActivator項目里任何類文件的namespace外部,但為了統一起見,一般都是放在Properties目錄下的AssemblyInfo類文件里,WebActivator就是這么做的。

       

      總結,好了,這就是WebActivator的全部源碼,實現起來其實很簡單,對吧?那以后項目再有類似需求的時候,就大膽使用這個類庫吧,另外NInject.MVC也是基于這個類庫來實現的。

      參考資料:

      http://blogs.msdn.com/b/davidebb/archive/2010/10/11/light-up-your-nupacks-with-startup-code-and-webactivator.aspx

      https://bitbucket.org/davidebbo/webactivator/src

      同步與推薦

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

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

      主站蜘蛛池模板: 国产成人高清精品亚洲| 久草热大美女黄色片免费看| 成人亚欧欧美激情在线观看| 色偷偷亚洲男人的天堂| 国产精品一区二区三区黄色| 日本欧美大码a在线观看| 亚洲中文字幕无码专区| 蜜桃一区二区三区在线看| 成人亚洲精品一区二区三区| 国产玖玖视频| 亚洲中少妇久久中文字幕| 日韩 高清 无码 人妻| 国产台湾黄色av一区二区| 丝袜高潮流白浆潮喷在线播放| 免费观看添你到高潮视频| 另类 专区 欧美 制服| 日韩精品中文字幕人妻| 久久99国产亚洲高清观看首页| 天天躁日日躁狠狠躁一区| 国产精品中文字幕在线| 人妻中文字幕不卡精品| 柠檬福利第一导航在线| 18禁超污无遮挡无码网址| 国产女同疯狂作爱系列| 亚洲欧洲一区二区免费| 色又黄又爽18禁免费网站现观看| 少妇人妻偷人偷人精品| 国内自拍第一区二区三区| 国产美女69视频免费观看| 天堂一区人妻无码| 人成午夜大片免费视频77777| 亚洲精品中文字幕一二三| 天堂国产一区二区三区| 国产精品第一页中文字幕| 亚欧洲乱码视频一二三区| 最新的国产成人精品2022| 奇米四色7777中文字幕| 一本色道久久综合无码人妻| 少妇宾馆粉嫩10p| 亚洲精品一区二区三区大桥未久| 久久精品国产99国产精品澳门|