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

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

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

      DynamicModuleUtility對象在.net不同版本下的兼容性問題

            Asp.Net MVC3 框架包含了一個Microsoft.Web.Infrastructure程序集,里面有個DynamicModuleUtility對象及其RegisterModule方法.用于在程序中動態注冊IHttpModule.一般來講模塊需在要在程序啟動之前注冊完成,所以調用這方法的程序一般都會在最開始處作PreApplicationStartMethod標記,比如:

      using System;
      using System.Web;
      using Microsoft.Web.Infrastructure.DynamicModuleHelper;
      
      [assembly:PreApplicationStartMethod(typeof(MyAppStart), "Start")]
      
      public class CoolModule : IHttpModule
      {
          // implementation not important 
          // imagine something cool here
      }
      
      public static class MyAppStart
      {
          public static void Start()
          {
              DynamicModuleUtility.RegisterModule(typeof(CoolModule));
          }
      }

            所以,如果直接將此調用寫在Global.asax.cs文件的Application_Start方法里,正常情況下會報"This method cannot be called during the application's pre-start initialization stage"異常,如下所示:

            但實際情況比上面所述要復雜一些.我有一套代碼,在公司里與家中同時開發.而將注冊代碼直接寫在Application_Start方法里的程序,在公司的電腦上居然可以正常執行,即不報錯,所有模塊都能正確的被注冊!這就讓我百思不得其解.由于代碼一樣,所引用的類庫也不曾發生變化,這讓我感覺是否是執行環境所造成的.我公司的電腦是64位win7,安裝了vs08,10,12,家里則是32位win7,只安裝了10.于是讓同事找了一臺64位的電腦重新部署運行,依舊報錯.正當我毫無頭緒的時候,忽然想起之前dudu發過的一篇文章,說是將園子從.Net 4.0升級到.Net 4.5之后遇到的一系列問題.會不會是這個原因呢?于是將家里的機器新裝了2012,再次運行,居然成功了.至此答案已經明了:是.Net 4.0與.Net 4.5.的兼容性問題.

            在詳細分析止問題之前,有幾個需要掌握的預備知識.

            1.CLR 目錄結構

            安裝一個特定版本的.Net后,會在三個位置布署這些dll.

            一個位于%Windows%\Microsoft.NET\Framework,跟據版本號的不同安裝到不同的目錄中去,又叫CSC目錄.默認情況下,使用CSC命令編譯程序進,程序所引用程序集的查找路徑為:程序的根目錄,CSC目錄,GAC目錄.

            自.Net 3.0開始,.Net安裝程序會在%Program Files%\Reference Assemblies\Microsoft\Framework處也布署一份相同的程序集.Visual Studio會優先從此處引用程序集.所以,使用VS編譯程序時,程序所引用程序集的查找路徑為:程序的根目錄,Reference Assemblies目錄,GAC目錄.

            最后一個位于%Windows%\Microsoft.NET\assembly,又叫GAC目錄,其本質是一個有多級子目錄的目錄,能夠同時布署相同文件名不同版本的dll,其主要為程序運行時服務.默認情況下,程序運行時,程序所引用程序集的查找路徑為:程序的根目錄,GAC目錄.

       

            2..Net版本對應關系

            我們一般所說的.Net2.0, 3.0, 3.5, 4.0, 4.5,是指它發布時候的打包版本,實際其由類庫,編譯器,運行時三部分組成,如下表:

      .NET打包版本 1 1.1 2 3 3.5 4 4.5
      類庫版本 1 1.1 2 3 3.5 4 4.5
      C#編譯器版本 1 1.1 2 2 3 4 4
      CLR版本 1 1.1 2 2 2 4 4

            3..Net更新策略

            到目前為止.Net使用過兩種更新策略.

            4.0及其之前的版本使用的是并存(side-by-side)更新.所有的版本都會存在于各自的目錄中.需要特別說明的是,.Net2.0, 3.0, 3.5是增量更新,即并沒有對已存在的程序集作出修改,而僅僅是新增了部分功能.所以對于公共部分,它們使用的都是相同的程序集.

            4.5使用的是覆蓋(in-place)更新,它會將自己所有文件覆蓋進4.0文件夾.也就是說,一旦更新至4.5,就一定會運行在4.5環境下.

       

            下面,我們再來仔細看一下為什么DynamicModuleUtility對象的RegisterModule方法在4.0環境下報錯,而在4.5環境下能正常執行.

            首先,反編譯方法

      public static void RegisterModule(Type moduleType)
      {
          if (DynamicModuleReflectionUtil.Fx45RegisterModuleDelegate != null)
              DynamicModuleReflectionUtil.Fx45RegisterModuleDelegate(moduleType);
          else
              LegacyModuleRegistrar.RegisterModule(moduleType);
      }

            從變量命名我們也可以猜出,其實此方法對于不同的執行環境也是不同的處理.下面來看看DynamicModuleReflectionUtil.Fx45RegisterModuleDelegate是如何生成的

      public static readonly Action<Type> Fx45RegisterModuleDelegate = GetFx45RegisterModuleDelegate();
      
      private static Action<Type> GetFx45RegisterModuleDelegate()
      {
          MethodInfo method = typeof(HttpApplication).GetMethod("RegisterModule", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Type) }, null);
          if (method == null) return null;
          return (Action<Type>) Delegate.CreateDelegate(typeof(Action<Type>), method);
      }

            這樣就明白了,原來程序是通過反射查看HttpApplication對象是否有RegisterModule方法.如果有則直接使用此方法.

            下面我們就分別查看.Net 4.0的HttpApplication與4.5的HttpApplication

            4.0的如下

            4.5的如下

            現在就明白了,原來4.5新增了兩個API,原生支持動態注冊IHttpModule,且可以在Application_Start()方法中注冊成功.

            現在回過頭來看如果是4.0環境,程序是如何處理的,他調用了LegacyModuleRegistrar內部類的RegisterModule方法

       

      private static readonly DynamicModuleReflectionUtil _reflectionUtil = DynamicModuleReflectionUtil.Instance;
      
      public static void RegisterModule(Type moduleType)
      {
          VerifyParameters(moduleType);
          if (_reflectionUtil != null)
          {
              lock (_lockObj)
              {
                  _reflectionUtil.ThrowIfPreAppStartNotRunning.Invoke();
                  AddModuleToClassicPipeline(moduleType);
                  AddModuleToIntegratedPipeline(moduleType);
              }
          }
      }

       

       

            哈哈,看名字就能明白,貌似如果不是在程序運行前注冊就會拋異常,是不是這樣呢?再次著看DynamicModuleReflectionUtil

      [CompilerGenerated]
      private Action <ThrowIfPreAppStartNotRunning>k__BackingField;
      
      public Action ThrowIfPreAppStartNotRunning
      {
          [CompilerGenerated]
          get
          {
              return this.<ThrowIfPreAppStartNotRunning>k__BackingField;
          }
          [CompilerGenerated]
          private set
          {
              this.<ThrowIfPreAppStartNotRunning>k__BackingField = value;
          }
      }
      
      public static readonly DynamicModuleReflectionUtil Instance = GetInstance();
      
      private static DynamicModuleReflectionUtil GetInstance()
      {
          try
          {
              if (Fx45RegisterModuleDelegate != null) return null;
              DynamicModuleReflectionUtil util = new DynamicModuleReflectionUtil();
              MethodInfo method = typeof(BuildManager).GetMethod("ThrowIfPreAppStartNotRunning", BindingFlags.NonPublic | BindingFlags.Static, null, Type.EmptyTypes, null);
              util.ThrowIfPreAppStartNotRunning = CommonReflectionUtil.MakeDelegate<Action>(method);
              CommonReflectionUtil.Assert(util.ThrowIfPreAppStartNotRunning != null);
              
              ......
              
              return util;
          }
          catch
          {
              return null;
          }
      }

            它將ThrowIfPreAppStartNotRunning委托,委托給了BuildManager類的ThrowIfPreAppStartNotRunning方法.

       

      internal static void ThrowIfPreAppStartNotRunning()
      {
          if (PreStartInitStage != PreStartInitStage.DuringPreStartInit) throw new InvalidOperationException(SR.GetString("Method_can_only_be_called_during_pre_start_init"));
      }

       

            原來,如果程序不是運行前狀態,就會拋異常!

            現在,整個運行邏輯就一目了然了.如果是運行于4.5環境,則會將此方法委托給新增的API,此API支持運行時動態增加IHttpModule.如果運行于4.0環境,則會檢查注冊時是哪一個階段.如果是運行時注冊,則會拋異常!

            PS:吐個槽,感覺4.5的覆蓋式更新,不是很穩啊,為什么就不能讓我們手動選擇運行環境呢?

       

            參考的文章:

            百年一遇的奇怪問題:當IE遇上.NET Framework 4.5

            善意提醒Dudu和其他打算升級到.NET Framework 4.5的同學

            What's New in ASP.NET 4.5 and Visual Studio 2012

            Missing Referenced Assemblies Folder for .NET 4.0

            C:\Program Files\Reference Assemblies for assemblies to reference in your code

            New Reference Assemblies Location

            再談CLR:GAC目錄的構造

            .NET Framework版本解析

       

      posted @ 2013-01-31 15:19  永遠的阿哲  閱讀(686)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲成人av在线资源| 日本高清色WWW在线安全| 大尺度国产一区二区视频| 日亚韩在线无码一区二区三区| 欧美精品18videosex性欧美| 日韩成人无码影院| 中文字幕成熟丰满人妻| 久久久久国产一区二区| 日韩乱码卡一卡2卡三卡四| 亚洲天堂亚洲天堂亚洲色图| 在线亚洲午夜片av大片| 成 人免费va视频| 99久久精品国产一区二区蜜芽| 婷婷99视频精品全部在线观看| 亚洲综合色网一区二区三区| 亚洲熟妇乱色一区二区三区| 成人AV无码一区二区三区| 国产精品一区中文字幕| 一区二区在线观看 激情| 天美传媒mv免费观看完整| av老司机亚洲精品天堂| 国产精品一线二线三线区| 亚洲国产成人久久77| 久久人妻少妇嫩草av无码专区| 亚洲区成人综合一区二区| 国产精品久久无码不卡黑寡妇| 草草线在成年免费视频2| 凤凰县| 国产精品一区二区三区黄色| 亚洲A综合一区二区三区| 性一交一乱一伦| 欧美国产成人久久精品| 国产无遮挡猛进猛出免费| 极品少妇无套内射视频| 午夜射精日本三级| 日韩精品二区三区四区| 亚洲精品av一二三区无码| 免费看一区无码无a片www| 国产欧美丝袜在线二区| 日韩国产成人精品视频| 欧美人与动牲猛交A欧美精品 |