.NET Standard详解
.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 Standard详解相关推荐
- PHP autoload机制详解
PHP autoload机制详解 转载自 jeakccc PHP autoload机制详解 (1) autoload机制概述 在使用PHP的OO模式开发系统时,通常大家习惯上将每个类的实现都存放在一个 ...
- head和tail命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/amosli/p/3496027.html 当要查看上千行的大文件时,我们可不会用cat命令把整个文件内容给打印出来,相 ...
- Python字符编码详解
Python字符编码详解 转自http://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html Python字符编码详解 本文简单介绍了各种常用的 ...
- php各种编码集详解和在什么情况下进行使用 [php 字符集 显示]
http://blog.cnsunrun.com/member/blog/blog_info/30/84 ----------------------------------------------- ...
- 全球著名音乐抓轨软件EAC 设置详解
EAC的作者Andre Wiethoff是德国多特蒙德大学计算机专业的一名学生,经常抓取和监听各种WAV文件,所以使用了许多抓音轨的软件,但令他不满意的是,这些软件只有 时基误差的校正,而CDROM在 ...
- Python中的__name__和__main__含义详解
背景 在写Python代码和看Python代码时,我们常常可以看到这样的代码: ? 1 2 3 4 5 def main(): ...... if __name__ == "__ma ...
- Android中measure过程、WRAP_CONTENT详解以及 xml布局文件解析流程浅析
转自:http://www.uml.org.cn/mobiledev/201211221.asp 今天,我着重讲解下如下三个内容: measure过程 WRAP_CONTENT.MATCH_PAREN ...
- Stuts的Web.xml 详解
1 定义头和根元素 部署描述符文件就像所有XML文件一样,必须以一个XML头开始.这个头声明可以使用的XML版本并给出文件的字符编码. DOCYTPE声明必须立即出现在此头之后.这个声明告诉服务器适用 ...
- nagios 3.2安装详解(一)
Nagios 安装详解 对于运维人员来说,获悉服务器状况的信息非常重要,针对监控服务,比较好的有cacti和nagios,cacti使用更简单一些,cacti主要是用来采集信息,CPU.MEM.流量等 ...
- Linux系统详解 系统的启动、登录、注销与开关机
Linux系统详解 第六篇:系统的启动.登录.注销与开关机 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://johncai.blo ...
最新文章
- ajax报403错,django使用ajax post数据出现403错误如何解决
- 如何让您的php也支持pthreads多线程
- Linux系统篇-文件系统虚拟文件系统
- content type 介绍
- bootstrap中表格大小设置_bootstrap 设置table - td宽度问题
- 利用airTest的图像实别技术测试Web应用
- 普通用户竟这样执行xp_cmdshell存储过程!
- pycharm导入本地文件,程序运行正常,但导入模块时出现红色波浪线
- 网吧版XP系统制作与优化终极版(转)
- 计算机二级考试办公软件高级应用题型,计算机二级考试题型
- 数据统计分析(SPSS)【8】
- 属牛的女孩取名:优美文雅、声声入耳的女孩名字
- 锐捷笔试题java_2018秋招锐捷笔试试题
- Axure旋转与移动效果
- 适合笔记本计算机玩的游戏,十款,笔记本电脑可以畅玩的单机游戏
- Java遍历jar包所有类-后续
- 4kw机柜无通道封闭CFD模拟分析及优化(下篇) -孙长青
- 修改 SSH 端口号
- UI设计师有哪些就业方向选择?
- 永恒之蓝漏洞复现(ms17-010)
热门文章
- 如何看出一个程序员的技术能力和水平?
- linux防挂马软件,Linux利用Python脚本检测网站挂马程序
- BI 工具常用图表用法
- 字谜游戏(b)C语言
- Arcgis修改栅格数据像素值
- vs2017配置 opengl + glfw + glad 环境
- BuBu笔记——MyBatis进阶-多表查询(秃头BUBu的超详细备注,一定要看哦)
- Scratch编程与数学之求累加和!
- 深度学习工程实践 5. libtorch+opencv使用复杂的训练分割模型(脸部,头发实现分割)
- 【历史上的今天】11 月 8 日:为开源献身的互联网之子;卷积神经网络 LeNet-5 问世;特斯拉发明遥控器