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

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

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

      MVC之前的那點事兒系列(2):HttpRuntime詳解分析(上)

      2014-05-29 08:42  湯姆大叔  閱讀(9986)  評論(7)    收藏  舉報

      文章內容

      從上章文章都知道,asp.net是運行在HttpRuntime里的,但是從CLR如何進入HttpRuntime的,可能大家都不太清晰。本章節就是通過深入分析.Net4的源碼來展示其中的重要步驟。請先看下圖:

       

      首先,CLR在初始化加載的時候,會加載一個非常重要的類AppManagerAppDomainFactory,這個類是做什么用的呢?首先這個類繼承了IAppManagerAppDomainFactory接口,而這個接口是是有個可供COM調用的Create方法,代碼如下:

       [ComImport, Guid("02998279-7175-4d59-aa5a-fb8e44d4ca9d"), System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]
          public interface IAppManagerAppDomainFactory { 
      #if !FEATURE_PAL // FEATURE_PAL does not enable COM 
              [return: MarshalAs(UnmanagedType.Interface)]
      #else // !FEATURE_PAL 
              Object Create(String appId, String appPath);
      #endif // !FEATURE_PAL
      
              Object Create([In, MarshalAs(UnmanagedType.BStr)] String appId, 
                            [In, MarshalAs(UnmanagedType.BStr)] String appPath);
       
       
              void Stop();
          } 

       

      我們來細看一下這個AppManagerAppDomainFactory是如何實現這個接口的,首先該類在默認的構造函數里,獲取了一個ApplicationManager的實例用于在Create方法里使用。代碼如下:

      [SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
      
      public AppManagerAppDomainFactory() {
      
          _appManager = ApplicationManager.GetApplicationManager();
      
          _appManager.Open();
      
      } 

       

      回到實現接口的Create方法,我們來看最重要的3行代碼:

      ISAPIApplicationHost appHost = new ISAPIApplicationHost(appId, appPath, false /*validatePhysicalPath*/);
      
       
      
      ISAPIRuntime isapiRuntime = (ISAPIRuntime)_appManager.CreateObjectInternal(appId, typeof(ISAPIRuntime), appHost,
      
              false /*failIfExists*/, null /*hostingParameters*/);
      
      
      isapiRuntime.StartProcessing();

       

      代碼的主要作用,就是通過ApplicationManager的CreateObjectInternal一系列操作,最終獲取ISAPIRuntime的實例,然后讓非托管代碼調用。所以說CreateObjectInternal方法在這里發揮了至關重要的功能:創建AppDomain,創建HostingEnvironment等一系列操作。

       

      首先來看看AppManagerAppDomainFactory的構造函數,其里面調用的ApplicationManager. GetApplicationManager()方法是一個單例的實現,代碼如下:

      public static ApplicationManager GetApplicationManager() {
      
          if (_theAppManager == null) {
      
              lock (_applicationManagerStaticLock) {
      
                  if (_theAppManager == null) {
      
                      if (HostingEnvironment.IsHosted)
      
                          _theAppManager = HostingEnvironment.GetApplicationManager();
      
       
      
                      if (_theAppManager == null)
      
                          _theAppManager = new ApplicationManager();
      
                  }
      
              }
      
          }
       
      
          return _theAppManager;
      
      }

       

      從代碼看,大家可能有點疑惑,為什么HostingEnvironment屬性IsHosted為true的時候會調用它的靜態方法GetApplicationManager()來獲取ApplicationManager的實例,這是因為ApplicationManager在后續的步驟創建HostingEnvironment對象并初始化的時候,將this自動傳遞給了HostingEnvironment對象實例(稍后在細說這個事情)。

       

      回頭再來看ApplicationManager實例的CreateObjectInternal方法,部分代碼如下:

      // get hosting environment
      
      HostingEnvironment env = GetAppDomainWithHostingEnvironment(appId, appHost, hostingParameters);
      
       
      
      // create the managed object in the worker app domain
      
      // When marshaling Type, the AppDomain must have FileIoPermission to the assembly, which is not
      
      // always the case, so we marshal the assembly qualified name instead
      
      ObjectHandle h = env.CreateWellKnownObjectInstance(type.AssemblyQualifiedName, failIfExists);
      
      return (h != null) ? h.Unwrap() as IRegisteredObject : null;

       

      通過代碼我們可以看到,首先要先得到HostingEnvironment的實例,然后通過該實例的CreateWellKnownObjectInstance方法返回上述Create方法需要的ISAPIRuntime的實例。那我們應該能想到GetAppDomainWithHostingEnvironment有2個作用,其一是先要獲取AppDomain,其二是獲取HostingEnvironment實例,來看看代碼是否如我們猜想的結果,先來看代碼:

      private HostingEnvironment GetAppDomainWithHostingEnvironment(String appId, IApplicationHost appHost, HostingEnvironmentParameters hostingParameters) {
      
          LockableAppDomainContext ac = GetLockableAppDomainContext (appId);
      
       
      
          lock (ac) {
      
              HostingEnvironment env = ac.HostEnv;
      
       
      
              if (env != null) {
      
                  try {
      
                      env.IsUnloaded();
      
                  } catch(AppDomainUnloadedException) {
      
                      env = null;
      
                  }
      
              }
      
              if (env == null) {
      
                  env = CreateAppDomainWithHostingEnvironmentAndReportErrors(appId, appHost, hostingParameters);
      
                  ac.HostEnv = env;
      
                  Interlocked.Increment(ref _accessibleHostingEnvCount);
              }
      
              return env;
      
          } 
      
      }

       

      代碼告訴我們,首先會檢查是否會有已經存在的AddDomain以及相應的HostingEnvironment實例,如果有返回,沒有就會創建一個新的。通過輾轉調用,最終來到一個私有方法CreateAppDomainWithHostingEnvironment,在這個300行的私有方法里,有我們所迷惑已久的東西。

      首先會有關于信任級別的代碼,比如是運行在FullTrust上還是MiddleTrust上,這里會有相應的處理代碼,由于我們這次代碼分析的重點不在這里,所以具體代碼就不細說了,來看看我們需要知道的代碼段:

      //  Create the app domain
      
       AppDomain appDomain = null;
      
      //  此處省略很多代碼
      
      if (isLegacyCas) {
      
          appDomain = AppDomain.CreateDomain(domainId,
      
      #if FEATURE_PAL // FEATURE_PAL: hack to avoid non-supported hosting features
      
                                              null,
      
      #else // FEATURE_PAL
      
      GetDefaultDomainIdentity(),
      
      #endif // FEATURE_PAL
      
      setup);
      
      }
      
      else {
      
          appDomain = AppDomain.CreateDomain(domainId,
      #if FEATURE_PAL // FEATURE_PAL: hack to avoid non-supported hosting features
      
                                              null,
      
      #else // FEATURE_PAL
      
         GetDefaultDomainIdentity(),
      
      #endif // FEATURE_PAL
      
         setup,
      
         permissionSet,
         fullTrustAssemblies /* fully trusted assemblies list: null means only trust GAC assemblies */);
      
      }

       

      通過代碼可以看出,這就是傳說中創建AppDomain的地方,后續所有的東西比如HttpRuntime, HttpContext都是依托于這個AppDomain,這就是為什么HttpContext為什么不能在多站點共享,而能安全存在于AppDomain的原因。

      繼續往下看,在創建AppDomain的代碼之后有幾行這樣的代碼:

      Type hostType = typeof(HostingEnvironment);
      
      String module = hostType.Module.Assembly.FullName;
      
      String typeName = hostType.FullName;
      
      ObjectHandle h = null;
      
      //  此處省略很多代碼
      
      h = Activator.CreateInstance(appDomain, module, typeName);
      
      //  此處省略很多代碼
      
      HostingEnvironment env = (h != null) ? h.Unwrap() as HostingEnvironment : null;
      
      //  此處省略很多代碼
      
      if (appDomainStartupConfigurationException == null) {
      
          env.Initialize(this, appHost, configMapPathFactory, hostingParameters, policyLevel);
      
       }
      
       else {
      
          env.Initialize(this, appHost, configMapPathFactory, hostingParameters, policyLevel, appDomainStartupConfigurationException);
      
      }
      
      return env;

       

      這就是創建HostingEnvironment實例的地方,創建實例以后,緊接著會調用Initialize方法來進行初始化,然后返回對象實例(注意該方法的第一個參數哦,是this,也就是ApplicationManager實例自身,就解釋了上面我所說的那個為什么能通過HostingEnvironment的靜態方法GetApplicationManager()來獲取ApplicationManager實例了)。

       

      通過這些代碼,我們就可以簡單的知道了,如何獲取ISAPIRuntime實例,從而為進入HttpRuntime做準備了。但是,我依然好奇HostingEnvironment的Initialize初始化方法到底都做了什么,好吧,我們來看看。

      OK,瞄到了一行重要的代碼:

      // initiaze HTTP-independent features
      
      HttpRuntime.InitializeHostingFeatures(hostingFlags, policyLevel, appDomainCreationException);

       

      該代碼進入HttpRuntime的靜態方法,接著調用HostingInt方法進行一些初始化工作,其中有一行代碼也是我們需要知道的,如下:

      // Initialize the build manager
      
      BuildManager.InitializeBuildManager();

       

      該BuildManager的InitializeBuildManager方法,會調用自己的Initialize方法進行初始化另外一些工作,其中包括編譯App_Code目錄下所有的.NET源代碼。由上面的一系列介紹我們知道,在一個AppDomain內,只有一個HostringEnvironment,所以該這個BuildManager的Initialize也就只執行一次,從而保證了編譯不出問題(源碼的注釋也是這么說的哦)。

       

      另外HostingInit方法里在初始化失敗的時候,在catch里有一行非常特殊的代碼:

      _hostingInitFailed = true;

       

      這是說在創建HostingEnvironment失敗的時候,會給HttpRuntime的HostingInitFailed賦值為True。后面的章節所討論的PreApplicationStartMethodAttribute的概念和WebActivator的入口都和這個值有關系,現在先不做討論,后面章節細再說。

       

      好了,回到AppManagerAppDomainFactory的Create方法,在得到ISAPIRuntime的實例,并且運行StartProcessing方法以后,會返回一個ObjectHandle對象給非托管代碼,其中包括了ISAPIRuntime的實例,代碼如下:

      return new ObjectHandle(isapiRuntime);

       

      非托管代碼接受ObjectHandle對象以后,要干什么呢?我們且看下篇文章的繼續分析。

      同步與推薦

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

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

      主站蜘蛛池模板: 国产精品国产三级国快看| 亚洲色www永久网站| 久久婷婷成人综合色综合| 一区二区三区AV波多野结衣| 伊人色综合一区二区三区影院视频| 免费无码又黄又爽又刺激| 婷婷六月色| 亚欧乱色国产精品免费九库| 精品一区二区中文字幕| 久久欧洲精品成av人片| 色悠悠久久精品综合视频| 成人白浆一区二区三区在线观看| 日韩精品无码一区二区视频 | 又爽又黄又无遮掩的免费视频| 石原莉奈日韩一区二区三区 | 久久综合干| 国产成人精品2021欧美日韩| 久久人人爽人人爽人人av| b站永久免费看片大全| 久久综合97丁香色香蕉| 国产精品老熟女露脸视频| 久久天天躁狠狠躁夜夜婷| 一区二区不卡99精品日韩| 熟妇人妻激情偷爽文| 国产极品粉嫩尤物一线天| 69天堂人成无码免费视频| 极品尤物被啪到呻吟喷水| 国产午夜福利av在线麻豆 | 亚洲香蕉伊综合在人在线| 国产日韩一区二区四季| 吕梁市| 天堂www在线中文| 色欲狠狠躁天天躁无码中文字幕 | 无码中文字幕av免费放| 国产精品伊人久久综合网| 亚洲永久精品ww47永久入口| 精品一区精品二区制服| 5D肉蒲团之性战奶水欧美| 亚洲中文字幕在线二页| 亚洲免费一区二区av| 激情综合一区二区三区|