在netcore迁移过程中,发现原有针对netframework平台编译的dll文件,可以直接在netcore的应用(netcoreapp.31)中加载并使用。对此感到比较好奇,本文就针对此知识点进行探究和梳理。
本次演示用到的几个项目说明: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所在的程序集有什么区别,并以此为突破口来探究相关技术点。
不过这里值得注意的时,此时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)程序集。