閱讀443 返回首頁    go 阿裏雲 go 技術社區[雲棲]


框架升級後某個類型所在程序集發生轉移,應用還能正常運行嗎?

所謂類型轉移(Type Forwarding)就是將定義在某個程序集中的類型轉移到另一個程序集中。我們先通過一個簡單的實例讓讀者朋友們對類型轉移有一個感官上的認識。我們利用Visual Studio創建一個針對.NET Framework 3.5的控製台應用,並編寫如下一端簡單的程序輸出兩個常用的類型(Function<T>和TimeZoneInfo)所在程序集的名稱。現在我們直接運行這個程序,會在控製台上得到如下所示的輸出結果,可以看出.NET Framework 3.5(CLR 2.0)環境下的這兩個類型定義在程序集System.Core.dll中。

   1: public class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         Console.WriteLine(typeof(Func<>).Assembly.FullName);
   6:         Console.WriteLine(typeof(TimeZoneInfo).Assembly.FullName);
   7:     }
   8: }

輸出結果:

image

現在我們對該程序的配置文件(App.config)作如下的修改,其目的在於采用CLR 4.0來運行該程序。再次運行該程序集之後,我們會在控製台上得到不一樣的輸出結果。通過如下所示的輸出結果我們可以看出當.NET Framework從3.5升級到4.0的時候,將原本定義在程序集System.Core.dll中的部分類型轉移到了程序集mscorelib.dll之中。

   1: <configuration>
   2:   <startup>
   3:     <supportedRuntime version="v4.0"/>
   4:   </startup>
   5: </configuration>

輸出結果:

image

跨程序集之間的類型轉移幫助框架或者類庫的提供者解決這樣的難題:某個類型在框架1.0版本的時候定義在中,當升級到2.0的時候被轉移到了中,使用舊版本的應用可以在的情況下直接對使用的升級後的框架程序集。類型轉移需要使用到一個特殊的特性TypeForwardedToAttribute,我們現在通過一個簡單的實例來演示如何利用這個特性來解決框架或者類庫升級過程在類型跨程序集轉移的問題。

這個演示的場景如上圖所示:代表應用的App.exe在編譯的時候引用了代表框架的程序集,具體使用的是定義其中的類型Foobar,框架進行升級之後新增了一個程序集,原來定義在Lib.dll中的類型Foobar被轉移到了Lib2.dll中。充分利用CLR針對類型轉移的支持,我們隻需要直接部署新版本的Lib.dll(不包含類型Foobar)和Lib2.dll,現有的程序能夠照常運行。

我們利用Visual Studio創建了如上圖所示的解決方案。類庫項目Lib1代表版本1.0的框架,我們將編譯生成的程序集名稱設置成Lib,並在其中定義了一個類型Foobar。控製台應用直接應用Lib1,並與其中編寫了如下一段簡單的程序,其目的在於確認類型Foobar所在的程序集。

   1: class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         Console.WriteLine(typeof(Foobar).AssemblyQualifiedName);
   6:         Console.Read();
   7:     }
   8: }
類庫項目Lib2和Lib3編譯生成代表框架升級之後的兩個程序集,我們通過修改項目屬性將目標程序集名稱設置成Lib和Lib2,Lib2具有針對Lib3的項目引用。我們在Lib3中重新定義了代表被轉移的類型Foobar,而Lib2實際上是一個空的項目。要體現類型Foobar從Lib.dll轉移到Lib2.dll,我們需要在Lib2項目上應用如下所示的一個特性(定義在AssemblyInfo.cs中)。
   1: [assembly:TypeForwardedTo(typeof(Foobar))] 

現在我們對整個解決方案進行編譯,然後定位到控製台App項目編譯後的輸出目錄(app\bin\debug),並將項目Lib1編譯生成的程序集Lib.dll刪除,而將Lib2和Lib3編譯生成的程序集Lib.dll和Lib2.dll拷貝到該目錄下。現在我們直接運行App.exe,我們會在控製台上得到如下所示的輸出結果。

image

如果某個項目應用了TypeForwardedToAttribute特性指向定義在另一個程序集中的被轉出類型,類型轉移相關的信息會體現在編譯生成的元數據中。就我們的實例而言,項目Lib2編譯的生成的程序集通過如下的元數據來指向被轉移出去的類型所在的目標程序集。

   1: .class extern forwarder Lib.Foobar
   2: {
   3:   .assembly extern Lib2
   4: }

當App.exe被執行的時候,由於元數據體現的依然是針對程序集Lib.dll的引用,所以CLR依然會試圖從該程序集中加載類型Foobar。但是通過分析程序集Lib.dll的元數據,CLR知道Foobar已經被轉移到程序集Lib2.dll中,所以定義在其中的同名類型Foobar最終會被加載。


作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-25 10:34:08

  上一篇:go  5分鍾用Jitpack發布開源庫
  下一篇:go  如何找到一個好的Joomla主機提供商