NETCore程序集複用技術:類型轉移(TypeForwarding)

背景介紹

在netcore遷移過程中,發現原有針對netframework平臺編譯的dll文件,可以直接在netcore的應用(netcoreapp.31)中加載並使用。對此感到比較好奇,本文就針對此知識點進行探究和梳理。

本次演示用到的幾個項目說明:
  • Tccc.TypeForwarding.Net451.SPI:代表針對net451平臺的類庫項目;
  • Tccc.TypeForwarding.NetApp:代表針對net451的控制檯應用項目;
  • Tccc.TypeForwarding.NetCoreApp:代表針對netcore3.1的控制檯應用項目;

Tccc.TypeForwarding.Net451.SPI中定義的類型Person源碼如下:

    public class Person
    {
        public string Name { get; set; }
        public string Age { get; set; }
        public void PrintInfo()
        {
            Console.WriteLine("Assembly FullName=" + typeof(string).Assembly.FullName);
            Console.WriteLine("Assembly Location=" + typeof(string).Assembly.Location);
        }
    }

兩個控制檯應用的Program源碼相同,均如下:

    internal class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person() { Name = "張三" };
            p1.PrintInfo();
            Console.ReadLine();
        }
    }
上述源碼的目的是對比應用程序在不同平臺的運行時,最常用的類型System.String所在的程序集有什麼區別,並以此爲突破口來探究相關技術點。
 

.NETFramewok平臺的特徵分析

現在啓動Tccc.TypeForwarding.NetApp得到的結果如下:
上述結果不出意料,就是證明了System.String類型的確位於mscorlib.dll中,同時根據路徑名稱也可以看得出此程序集就是位於.NETFramework運行時中。
 
進一步的,針對Tccc.TypeForwarding.Net451.SPI反編譯可以看到程序集metadata確實聲明瞭對mscorlib的引用。

NETCore平臺的特徵分析

現在來運行Tccc.TypeForwarding.NetCoreApp程序,看看輸出結果有什麼變化。
單純看控制檯輸出好像也沒有啥奇怪的,就是程序集名稱改爲System.Private.CoreLib,同時路徑變爲了netcore3.1運行時的位置。上述結果也僅說明了,System.String類型在netcore3.1平臺上的代碼實現是在System.Private.CoreLib程序集而已。這個知識點對接觸過netcore的同學應該都有所瞭解。


不過這裏值得注意的時,此時Tccc.TypeForwarding.Net451.SPI的目標平臺依然是net451,而且根據上面反編譯我們明明看到Tccc.TypeForwarding.Net451.SPI是引用了NET Framework的著名程序集mscorlib呢?

這裏我們再次反編譯netcore3.1目錄下的Tccc.TypeForwarding.Net451.SPI程序集,驗證確實還存在mscorlib的引用;

既然確實依賴了mscorlib,那就看看程序內存中加載了哪裏的mscorlib文件。
PS:由於演示程序直接在VS中可方便查看,如果讀者是以現有程序分析驗證則可通過windbg的SOS擴展命令dumpdomain查看分析。
顯然,雖然加載的都是mscorlib.dll文件,但是位置不同了:C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.21\mscorlib.dll
既然位置不同,是否內部實現也不同了呢?反編譯看看:
 
打開此程序集後,就沒有找到預期的System.String類型,並且壓根就不存在其它類型的定義實現。看來這個mscorlib是個空殼文件。
那麼真正的類型源碼在哪呢?這就需要對反編譯工具微調,改爲IL格式查看,如下圖,我們再次看到了熟悉的System.Private.CoreLib。
原來如此,這是把對mscorlib的引用,重定向到了System.Private.CoreLib程序集中。
這種技術稱爲TypeForwarding(類型轉移),而這個空殼的mscorlib稱爲墊片(shim)程序集。

總結

以上是以類型System.String爲例進行分析探究的,其它常用的類型如Int32、Task等,大家可自行實踐驗證看看。
另外,由於是微軟官方支持的程序集複用,因此在做netcore遷移時,只要沒有使用NETFramework特有的類型,那麼原程序集不需要重新編譯就可以放心的部署倒NetCore應用中。這在多部門、多應用的遷移過程中,大大降低了各組間的相互依賴。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章