.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.pswp.cn/news/285568.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285568.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285568.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(四)

【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(一) 【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(二) 【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(三) 【專升本計算機】2021年甘肅省專升本計算機全真模擬試題(四) 【專升本計算機】2021…

14.6.3.1 The InnoDB Buffer Pool

14.6.3.1 The InnoDB Buffer PoolInnoDB 保持一個存儲區域被稱為buffer pool 用于cache數據和索引在內存里,知道InnoDB buffer pool 如何工作,利用它來保持頻繁訪問的數據在內存里,是MYSQL 調優的一個重要方面。你可以配置InnoDB buffer pool的各個方面來改善性能:理想情況下,你…

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; } }由…

yii2筆記: 單元測試

使用composer方式安裝yii2-app-basic (https://github.com/yiisoft/yii2-app-basic/blob/master/README.md) 裝好后既可以使用 建一個Model文件EntryForm.php在models目錄下 <?phpnamespace app\models;use Yii; use yii\base\Model;class EntryForm extends Model {public…

[轉]Python 列表(List) 的三種遍歷(序號和值)方法

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

C語言試題103之輸出特殊圖案,請在 c 環境中運行,看一看

?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 1、題目 題目:輸出特殊圖案,請在 c 環境中運行,看一看 2 、溫馨提示 想獲取更多C語言題目請猛搓這…

Web頁面獲取用戶控件頁面中服務器控件的值

用戶控件頁面后臺&#xff1a; public string P_Name{get { return txt_P_name.Value; }set { txt_P_name.Value value; }} Web頁面后臺&#xff1a; if (head.P_Name ! "")//head為用戶控件的標簽名{strwhere " and a.P_NAME like %" head.P_Name &qu…

【C#程序設計】教學講義——第一章:C#語言概述

文章目錄 1.1 認識Visual C#1.2 .NET Framework 3.51.3 Visual C# 2008集成開發環境1.4 使用幫助系統1.5 用C#創建Windows應用程序1.6 用C#創建控制臺應用程序1.1 認識Visual C# 1.1.1 C#語言的由來 1.C和C++ 一直是商業軟件開發領域中最具有生命力的語言; 利用C和C++語言開…

Kafka學習征途:基于Docker搭建Kafka環境

【Kafka】| 總結/Edison Zhou1準備工作這里我們使用一臺Linux CentOS系統的服務器來模擬三個Kafka Broker的偽集群&#xff08;即一臺server上開三個不同端口&#xff09;環境用于學習測試&#xff0c;大概的準備工作有兩個&#xff1a;安裝Docker# wget https://mirrors.aliyu…

C語言試題104之輸出 9乘9 口訣

?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 1、題目 題目:輸出 9乘9 口訣。 分析:分行與列考慮,共 9 行 9 列,i 控制行,j 控制列 2 、溫馨提…

160809308周子濟第7次作業

#include<stdio.h> #include<string.h> int main() {char name[20];int length,i,count[26]{0};printf("輸自己名拼音&#xff1a;");scanf("%s",name);lengthstrlen(name);for(i0;i<length;i)count[name[i]-a];for(i0;i<26;i)printf(&…

【Envi風暴】基于ENVI平臺提取ASTER DEM完整操作步驟(附案例數據)

本文講解在Envi平臺上,基于Aster影像數據,提取DEM的完整操作流程及注意事項,附實驗數據下載練習。 文章目錄 一、內容和目的二、提取DEM的原理三、ENVI平臺提取DEM流程四、DEM質量評估五、注意事項六、案例數據下載地址一、內容和目的 采用ASTER立體像對提取DEM,數據源: …

HashCode和hashMap、hashTable

2019獨角獸企業重金招聘Python工程師標準>>> 什么是哈希碼(HashCode) 在Java中&#xff0c;哈希碼代表對象的特征。 例如對象 String str1 “aa”, str1.hashCode 3104 String str2 “bb”, str2.hashCode 3106 String str3 “aa”, str3.hashCode 3104 根據Hash…

在OpenCloudOS使用snap安裝.NET 6

開源操作系統社區 OpenCloudOS 由騰訊與合作伙伴共同倡議發起&#xff0c;是完全中立、全面開放、安全穩定、高性能的操作系統及生態。OpenCloudOS 沉淀了多家廠商在軟件和開源生態的優勢&#xff0c;繼承了騰訊在操作系統和內核層面超過10年的技術積累&#xff0c;在云原生、穩…

C語言試題108之打印出所有的“水仙花數”,所謂“水仙花數”是指一個三位數,其各位數字立方和等于該數 本身。例如:153 是一個“水仙花數”,因為 153=1 的三次方+5 的三次方+3 的三次方。

?作者簡介:大家好我是碼莎拉蒂,CSDN博客專家?????? ??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 1、題目 題目:打印出所有的“水仙花數”,所謂“水仙花數”是指一個三位數,其各位數字立方和等于該…

code vs1517 求一次函數解析式(數論 純數學知識)

1517 求一次函數解析式 時間限制: 1 s空間限制: 128000 KB題目等級 : 白銀 Silver題解查看運行結果題目描述 Description相信大家都做過練習冊上的這種 題吧&#xff1a; 已知一個一次函數的圖像經過點&#xff08;x1,y1&#xff09;、&#xff08;x2,y2&#xff09;,求該函數的…