.NET 中的引用程序集

.NET 中的引用程序集

Intro

在 .NET 里有一种特殊的程序集叫做 ReferenceAssembly(引用程序集),引用程序集(Reference Assemblies) 是一种特殊类型的程序集,它只包含表示库的公共 API 所需的最少元数据量。它们包括在生成工具中引用程序集时所需的所有成员的声明,但不包括所有成员实现以及对其 API 协定没有明显影响的私有成员的声明。相比较下,常规程序集称为“实现程序集” (implementation assemblies)。

Why

既然我们有实现程序集,为什么还要有引用程序集呢?

使用引用程序集,开发人员可以生成面向特定库版本的程序,而无需具有该版本的完整实现程序集。因为不包含实现,引用程序集会更小一些,加载和解析都会更快一些。

这类似于我们和第三方的开发者约定的 API 规范,我们可以先给出 API 的请求和响应而无需提供实现以不 block 第三方开发者的进度,毕竟他们只关心 API 是什么样的而不关心实现。

若要使用项目中的某些 API,必须添加对其程序集的引用。可以将引用添加到实现程序集,也可以将其添加到引用程序集。建议在引用程序集可用时使用它。这样做可确保仅使用目标版本中受支持的 API 成员,即供 API 设计人员使用。使用引用程序集可确保不依赖于实现详细信息。

How

在 .NET Core 3.0 之前很多程序集都是发布 NuGet 包的,对于 .NET Core 3.0 和更高版本,核心框架的引用程序集位于 Microsoft.NETCore.App.Ref 包中,一般情况下是不需要的,因为引用程序集也会随着 .NET SDK 一起发布,你可以在 SDK 的安装目录下的 packs 目录下找到对应框架版本的引用程序集

下面是我电脑上 SDK 里的框架引用程序集的一个示例

dcc2e4ef0589d6c0777eb0c4b53c739c.png

对于引用程序集只能用于编译,这种程序集会有一些特殊,反编译的话会看到有一个 ReferenceAssembly 的程序集 Attribute,下面是我从上面的目录中找的 System.Text.Json 的反编译结果,可以看到有一个 ReferenceAssembly 的 attribute

9b077fe5d4bf4707e810483230c685da.png

Reference Assembly

再看一下 JsonNode 的实现

44649644011899c079fc0d5aa0017de1.png

我们再找一个实现的程序集对比一下

638b33c450515e7bcc5198f633891065.png

Implementation assembly

429b84956021da8d95b432f246fac5e3.png

由于它们不包含任何实现,因此无法加载引用程序集用于执行。如果尝试这样做,则会导致 System.BadImageFormatException,可能会遇到 Reference assemblies can only be loaded in the Reflection-only loader context. 这样的错误。

如果要检查引用程序集的内容,你可将其加载到 .NET Framework 中的仅反射上下文中(使用 Assembly.ReflectionOnlyLoad 方法),或者加载到 .NET Core 中的 MetadataLoadContext。

More

经常看源码的童鞋,一定会注意到,dotnet/runtime 中很多的类库的结构都是类似下面这样的

1ed6e211b875bf9dfa54d998172f504c.png

runtime library structure

大家会看到第一个目录是 ref,也就是用来生成引用程序集的,src 则是包含了实现的项目源码,test 则是一些测试用例 https://github.com/dotnet/runtime/blob/89962a54d60e4d9c9837012d1729c5a72ec748cd/src/libraries/Microsoft.Extensions.Configuration/

ref 项目引用的其他项目也都是直接引用的 ref 项目 https://github.com/dotnet/runtime/blob/89962a54d60e4d9c9837012d1729c5a72ec748cd/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.csproj

1acb8ede1577baae148121c50cd54ba1.png

查看 ref 项目的代码,可以发现和反编译的效果是一样的,都是空实现或者 throw null https://github.com/dotnet/runtime/blob/89962a54d60e4d9c9837012d1729c5a72ec748cd/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.cs#L7

81f578d6750843a11bffb139f1c0abb4.png

最近在做 dotnet-exec 这个小工具的时候就遇到了引用程序集的问题,起初没怎么理解这个引用程序集,在编译代码时使用的是引用程序集,在执行代码时也是用的引用程序集,在执行时 load 程序集的时候就报了前面提到的

BadImageException Reference assemblies can only be loaded in the Reflection-only loader context.

在看到 Youtube 上这个介绍 Reference Assembly 的视频(https://www.youtube.com/watch?v=EBpY1UMHDY8&list=PLRAdsfhKI4OX1cBGL2IXuEq1yzpDyKlwf&index=1&t=3s)之后才恍然大悟,原来如此。。。虽然视频是以 .NET Framework 为例讲解的,.NET Core 也类似,感兴趣的可以看一下

在 VS 里经常会遇到 F12 之后看到的实现都是 throw null,猜测也是因为这个原因,在编译时 VS 使用的是引用程序集来提高性能

最后有没有好奇 ref 项目和 src 项目的差别在哪里?表面上看 ref 项目文件里的东西好像没什么特别的啊,利用了之前我们提到过的 Directory.Build.props 来为大多数项目统一配置了,感兴趣的同学可以根据下面的链接自己探索一下

https://github.com/dotnet/runtime/blob/89962a54d60e4d9c9837012d1729c5a72ec748cd/src/libraries/Directory.Build.props#L8

https://github.com/dotnet/runtime/blob/89962a54d60e4d9c9837012d1729c5a72ec748cd/eng/referenceAssemblies.props#L22

906ee2dcc56f4bf8d7540319f02ba060.png

References

  • https://github.com/dotnet/docs/pull/14393

  • https://github.com/dotnet/docs/issues/2638

  • https://github.com/dotnet/roslyn/blob/main/docs/features/refout.md

  • https://docs.microsoft.com/en-us/dotnet/standard/assembly/reference-assemblies

  • https://docs.microsoft.com/zh-cn/dotnet/standard/assembly/reference-assemblies

  • https://www.youtube.com/watch?v=EBpY1UMHDY8&list=PLRAdsfhKI4OX1cBGL2IXuEq1yzpDyKlwf&index=1&t=3s

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285568.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(四)

【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(一) 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(二) 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(三) 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(四) 【专升本计算机】2021…

C语言试题105之要求输出国际象棋棋盘

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:要求输出国际象棋棋盘。 分析:用 i 控制行,j 来控制列,根据 i+j 的和的变化来控制…

一个js的动画,以前以为只有flash可以实现

11年刚干这行的时候,看到这种什么百叶窗的动画,以为都是flash实现的,最近突然灵光一闪,想到了用js实现(虽然我不是做前端的,本人做.net)。代码虽然实现了,但是比较乱,先上…

[转]docker入门(利用docker部署web应用)

前言:本课程是在慕课网上学习 第一个docker化的java应用 课程时所做的笔记,供本人复习之用 目录 第一章 什么是docker 1.1 docker的发展史 1.2 docker国内应用史 1.3 什么是Docker 第二章 了解docker 2.1 docker思想 2.1.1 集装箱 2.1.2 标准化 2.1.3 隔离 2.2 dock…

【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(五)

【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(一) 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(二) 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(三) 【专升本计算机】2021年甘肃省专升本计算机全真模拟试题(四) 【专升本计算机】2021…

如何让 EF Core 6 支持 DateOnly 类型

前言上次,我们发现《DateOnly 和 TimeOnly 类型居然不能序列化》。但问题还不仅仅如此。问题重现假设有下列实体类:public class User {public int Id { get; set; }public string Name { get; set; } public DateOnly Birthday { get; set; } }由…

[转]Python 列表(List) 的三种遍历(序号和值)方法

if __name__ __main__:list [html, js, css, python]for i in list:print(list.index(i), i)# 方法1print( 遍历列表方法1:)for i in list:print ("序号:%s 值:%s" % (list.index(i) 1, i))print (\n遍历列表方法2:)…

C语言试题103之输出特殊图案,请在 c 环境中运行,看一看

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:输出特殊图案,请在 c 环境中运行,看一看 2 、温馨提示 想获取更多C语言题目请猛搓这…

Kafka学习征途:基于Docker搭建Kafka环境

【Kafka】| 总结/Edison Zhou1准备工作这里我们使用一台Linux CentOS系统的服务器来模拟三个Kafka Broker的伪集群(即一台server上开三个不同端口)环境用于学习测试,大概的准备工作有两个:安装Docker# wget https://mirrors.aliyu…

C语言试题104之输出 9乘9 口诀

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:输出 9乘9 口诀。 分析:分行与列考虑,共 9 行 9 列,i 控制行,j 控制列 2 、温馨提…

【Envi风暴】基于ENVI平台提取ASTER DEM完整操作步骤(附案例数据)

本文讲解在Envi平台上,基于Aster影像数据,提取DEM的完整操作流程及注意事项,附实验数据下载练习。 文章目录 一、内容和目的二、提取DEM的原理三、ENVI平台提取DEM流程四、DEM质量评估五、注意事项六、案例数据下载地址一、内容和目的 采用ASTER立体像对提取DEM,数据源: …

HashCode和hashMap、hashTable

2019独角兽企业重金招聘Python工程师标准>>> 什么是哈希码(HashCode) 在Java中,哈希码代表对象的特征。 例如对象 String str1 “aa”, str1.hashCode 3104 String str2 “bb”, str2.hashCode 3106 String str3 “aa”, str3.hashCode 3104 根据Hash…

C语言试题108之打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数 本身。例如:153 是一个“水仙花数”,因为 153=1 的三次方+5 的三次方+3 的三次方。

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该…

【ArcGIS风暴】ArcGIS Editor for OSM中文教程(1):软件下载及安装

OpenStreetMap ArcGIS编辑器允许你使用ArcGIS工具为OpenStreetMap数据工作。这个桌面工具允许你加载OpenStreetMap数据并将其存储在地理数据库中 。你可以使用ArcMap熟悉的编辑环境的创建,修改,做网络分析,或者更新数据。一旦您完成编辑后,你可以回到编辑修改OSM使它们提供…

使用Scrapy时出现虽然队列里有很多Request但是却不下载,造成假死状态

2019独角兽企业重金招聘Python工程师标准>>> DOWNLOAD_TIMEOUT Default: 180 The amount of time (in secs) that the downloader will wait before timing out. Note This timeout can be set per spider using download_timeoutspider attribute and per-request …

为什么 Istio 要使用 SPIRE 做身份认证?

今年 6 月初,Istio 1.14 发布 [1] ,该版本中最值得关注的特性是新增对 SPIRE 的支持。SPIFFE[2] 和 SPIRE 都是 CNCF 孵化项目,其中 SPIRE 是 SPIFFE 的实现之一。本文将带你了解 SPIRE 对于零信任架构的意义,以及 Istio 是为何使…

C语言试题106之有一对兔子,从出生后第 3 个月起每个月都生一对兔子,小兔子长到第三个月 后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?

1、题目 题目:有一对兔子,从出生后第 3 个月起每个月都生一对兔子,小兔子长到第三个月 后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 分析:兔子的规律为数列 1,1,2,3,5,8,13,21… 2 、温馨提示 想获取更多C语言题目请猛搓这里==========》200个C语言…

【ArcGIS风暴】ArcGIS Editor for OSM中文教程(2):下载及加载OSM数据

本文讲解在ArcGIS中借助OpenStreetMap工具下载并加载OSM数据。 文章目录 1. 下载OSM数据2. 加载OSM数据1. 下载OSM数据 在工具箱中双击Download OSM Data(XAPI)工具。 Download URL:http://www.overpass-api.de/api/xapi_meta? Downlaod Extent:与图层lanzhou相同

Object.observe将不加入到ES7

先请看 Object.observe 的 API Object.observe(obj, callback[, acceptList])它用来监听对象的变化,当给该对象添加属性,修改属性时都会被依次记录下来 看一个示例 var person {} Object.observe(person, function(arr) {var change arr[0]console.log…

Kafka学习征途:.NET Core操作Kafka

【Kafka】| 总结/Edison Zhou1可用的Kafka .NET客户端作为一个.NET Developer,自然想要在.NET项目中集成Kafka实现发布订阅功能。那么,目前可用的Kafka客户端有哪些呢?目前.NET圈子主流使用的是 Confluent.Kafkaconfluent-kafka-dotnet : htt…