所謂類型轉移(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: }
輸出結果:
現在我們對該程序的配置文件(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>
輸出結果:
跨程序集之間的類型轉移幫助框架或者類庫的提供者解決這樣的難題:某個類型在框架1.0版本的時候定義在程序集A中,當升級到2.0的時候被轉移到了程序集B中,使用舊版本的應用可以在不做任何修改的情況下直接對使用的升級后的框架程序集。類型轉移需要使用到一個特殊的特性TypeForwardedToAttribute,我們現在通過一個簡單的實例來演示如何利用這個特性來解決框架或者類庫升級過程在類型跨程序集轉移的問題。
這個演示的場景如上圖所示:代表應用的App.exe在編譯的時候引用了代表框架的程序集Lib.dll,具體使用的是定義其中的類型Foobar,框架進行升級之后新增了一個程序集Lib2.dll,原來定義在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: }
1: [assembly:TypeForwardedTo(typeof(Foobar))]
現在我們對整個解決方案進行編譯,然后定位到控制臺App項目編譯后的輸出目錄(app\bin\debug),并將項目Lib1編譯生成的程序集Lib.dll刪除,而將Lib2和Lib3編譯生成的程序集Lib.dll和Lib2.dll拷貝到該目錄下。現在我們直接運行App.exe,我們會在控制臺上得到如下所示的輸出結果。
如果某個項目應用了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最終會被加載。
文章列表