小当家ISV
互联网高新技术服务商

全球共有10多个国家和地区1000多个平台,20万+商户使用

.NET Standard详解

作者:    谭智文       发布时间:     2023-04-15          392      分类专栏: 后端开发

.NET Standard是一套协议规范,不像.NET Framework,后者是一个完整的技术框架,而前者只是定义了一套规范,遵守这套规范的.NET Standard类库可以被不同.NET框架引用,比如.NET Core项目和.NET Framework项目都可以引用这个类库。

Standard这个单词就是标准、规范的意思,.NET Standard旨在建立一套标准,解决不同.NET框架之间的兼容性问题。

关于.NET Standard的概念以及版本支持的知识,请大家参考MSDN的介绍:https://docs.microsoft.com/zh-cn/dotnet/standard/net-standard

下面我们用.NET Core和.NET Framework框架为例介绍.NET Standard为什么能解决不同.NET框架之间的兼容性问题

在.NET Core项目中,我们所使用的类所在的程序集从表面上看和.NET Framework是一模一样的,那既然他们使用的程序集是完全一样的,为什么前者可以跨平台,而后者不可以呢?关于这个问题,请看我的另一篇文章:.NET Framework类型转移。

说到这里,我想到一个问题,为什么微软要使用类型转移这个技术呢?直接使用对应框架的对应程序集不就可以了吗。我是这样想的:因为.NET Framework框架出来的时间比.NET Core框架出来的时间早很多,微软为了让大家能够适应.NET Core,所以每个类所在的程序集都没有变化,但实际上,微软使用类型转移技术在背后把原程序集都重定向到了.NET Core的程序集上。这个操作是透明的,所以我们感觉不到。

下面我们用代码说话吧

我们新建一个.NET Standard的类库,版本为2.0。然后新建一个Utils的类,代码如下:

public class Utils

    {

        public static void PrintAssemblyNames()

        {

            Console.WriteLine(typeof(Dictionary<,>).Assembly.FullName);

            Console.WriteLine(typeof(SortedDictionary<,>).Assembly.FullName);

         

        }

    }

我们输出了这两个类型所在的程序集。

然后我们新建两个项目,一个.NET Framework 4.7.2,一个.NET Core 3.1,这两个项目都是控制台程序,代码如下:

static void Main(string[] args)

        {

            Console.WriteLine(".NET Framework 4.7.2");

            Utils.PrintAssemblyNames();

            Console.ReadKey();

        }

static void Main(string[] args)

        {

            Console.WriteLine(".NET Core 3.1");

            Utils.PrintAssemblyNames();

 

            Console.ReadKey();

        }

这两个项目都只做了一件事,在当前项目中输出上面两个类所在的程序集的信息。下面我们看一下输出结果:

可以看到,在不同的项目中输出的程序集是不一样的。下面我们就来了解一下为什么不一样。

首先我们看Dictionary类,在.NET Standard项目中,转到Dictionary的定义,在页面顶部可以看到它所在的程序集是netstandard。因为.NET Framework的版本是4.7.2,运行时是CLR4.0,所以我们找到CLR4.0下的netstandard.dll,这个dll在我电脑上的路径是:C:\Windows\Microsoft.NET\Framework\v4.0.30319\netstandard.dll,找到后使用ildasm.exe打开这个dll,双击MANIFEST,点击查找System.Collections.Generic.Dictionary,可以看到如下代码:

.class extern forwarder System.Collections.Generic.Dictionary`2

{

  .assembly extern mscorlib

}

这个代码的意思是System.Collections.Generic.Dictionary类被定义在程序集mscorlib中,所以在.NET Framework4.7.2项目下,Dictionary类所在的程序集是mscorlib。

使用同样的方法,查找到netstandard在.NET Core下面的路径:C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.4\netstandard.dll,同样反编译这个dll,可以看到如下代码:

.class extern forwarder System.Collections.Generic.Dictionary`2

{

  .assembly extern System.Collections

}

.class extern forwarder System.Collections.Generic.SortedDictionary`2

{

  .assembly extern System.Collections

}

这两个类型都被重定向到System.Collections中,但是从输出结果中可以看到Dictionary的结果集是System.Private.CoreLib,这是为什么呢?因为它被二次转移了,为了验证这个问题,我们在同样的目录下找到System.Collections.dll,使用反编译工具打开这个dll,可以看到如下代码:

.class extern forwarder System.Collections.Generic.Dictionary`2

{

  .assembly extern System.Private.CoreLib

}

所以在.NET Core的项目中Dictionary类型所在的程序集是System.Private.CoreLib。

其实这里有个容易被大家忽视的细节,从这个细节也可以看出这两个类所在的程序集。我们在.NET Core和.NET Framework项目中也定义一个Dictionary类,然后转到它的定义,可以看出在.NET Core项目中,它所在的程序集是System.Collections,但是因为有二次转移,所以最终所在程序集是System.Private.CoreLib;在.NET Framework项目中,它所在的程序集就是mscorlib;但是在.NET Standard项目中,它所在的程序集是netstandard。

.NET Standard类库之所以能够兼容其他的.NET框架,就是因为这个netstandard.dll。在这个项目类库中所有类型的所在程序集都是netstandard.dll,然后所有的.NET框架也都实现了这个程序集中的类型,通过类型转移(也称垫片程序集),最终调用的程序集是引用这个类库的项目的运行时程序集,这就是.NET Standard能够兼容其他.NET框架的原因。

所属分类: 后端开发
.net core基于HttpClient实现的网络请求库
软件测试目的,为什么进行测试

小当家,帮您把生意越做越大!

小当家ISV,重庆APP开发,小程序开发,软件系统开发 地址:重庆市南岸区南坪万达广场写字楼2栋19-6 联系电话:023-81361879

ICP备案号:渝ICP备15003473-1 增值电信业务许可证: 渝B2-15003473 渝公网安备 50010802005103号

友情链接: 小当家点餐收银系统   MagicShop商城  重庆微信营销  重庆智能家居  重庆红岭医院 

重庆小当家互联网信息技术有限公司