NETCore程式集複用技術:型別轉移(TypeForwarding)

chenzk發表於2022-01-25

背景介紹

在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得到的結果如下:
NETCore程式集複用技術:型別轉移(TypeForwarding)
上述結果不出意料,就是證明了System.String型別的確位於mscorlib.dll中,同時根據路徑名稱也可以看得出此程式集就是位於.NETFramework執行時中。
 
進一步的,針對Tccc.TypeForwarding.Net451.SPI反編譯可以看到程式集metadata確實宣告瞭對mscorlib的引用。
NETCore程式集複用技術:型別轉移(TypeForwarding)

NETCore平臺的特徵分析

現在來執行Tccc.TypeForwarding.NetCoreApp程式,看看輸出結果有什麼變化。
NETCore程式集複用技術:型別轉移(TypeForwarding)
單純看控制檯輸出好像也沒有啥奇怪的,就是程式集名稱改為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的引用;

NETCore程式集複用技術:型別轉移(TypeForwarding)

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

總結

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

相關文章