包、元包和框架(.NET Core 指南)
.NET Core
是一種由 NuGet
包組成的平臺。 有些產品體驗受益於包的細粒度定義,而另一些受益於粗粒度的定義。 為了適應這種二元定義,一款好的產品應該作為一組細粒度的包釋出,並在更粗的粒度組塊中進行分發,單個包的正式的名字叫做元包。
每個 .Net Core
包都支援以框架形式通過多個 .Net
實現程式碼執行。 其中有些框架是傳統框架,例如表示 .NET Framework
的 net46
。 而另一些則是新框架,可視為是“基於包的框架”,這種是框架的另外一種新的定義模型。 這些基於包的框架整個都是由包組成的,它們自身也被定義成包,這就在包與框架之間形成了一種比較密切的關係。
包
.NET Core
被分成一組包,它們提供了基元型別,以及更高層的資料型別,應用組合型別和通用實用工具。 每一個包都代表著單獨的同名程式集。 例如,System.Runtime
這個包就包含了 System.Runtime.dll
程式集。
以細粒度方式定義這些包具有以下好處:
- 細粒度的包可以在它自己的計劃內交付,只需完成僅對相關的其他有限的包進行測試即可。
- 細粒度的包可以提供不同的 OS 和 CPU 支援。
- 細粒度的包可以單獨依賴於某一個庫。
- 應用可以變得更小,因為沒有引用的包不會變成應用發行的一部分。
上述某些好處只適用於某些特定場合。 例如,.NET Core
的所有包通常都會在同一計劃內提供對同一平臺的支援。 在這種情況下,補丁與更新會以小的單獨包的形式釋出和安裝。 由於這種小範圍的變化,補丁的驗證與時間花費,都可以限制到單個庫的需求範圍中。
以下是 .NET Core
重要的 NuGet
包列表:
System.Runtime
- 最基礎的.NET Core
包,包括Object、String、Array、Action
和IList<T>
。System.Collections
- 一組(主要)泛型集合,包括List<T>
和Dictionary<TKey,TValue>
。System.Net.Http
- 一組用於HTTP
網路通訊的型別,包括HttpClient
和HttpResponseMessage
。System.IO.FileSystem
- 一組用於讀寫到本地或網路磁碟儲存的型別,包括File
和Directory
。System.Linq
- 一組用於查詢物件的型別,包括Enumerable
和ILookup<TKey,TElement>
。System.Reflection
- 一組用於載入、檢查和啟用型別的型別,包括Assembly
、TypeInfo
和MethodInfo
。
通常,包含元包要比包含各個包更加簡單可靠。 但是當需要單個包時,可以按以下示例所示的那樣來包含它,此示例引用 System.Runtime
包。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Runtime" Version="4.3.0" />
</ItemGroup>
</Project>
元包
元包就是一個 NuGet
包約定,描述了一組意義相關的包。 開發團隊利用依賴項來描述這一組包。 他們通過這一組包來描述一個框架,然後有選擇地釋出出去。
預設情況下,早期版本的 .NET Core
工具(同時基於 project.json
和 csproj
的工具)指定一個框架和一個元包。 但目前,由目標框架隱式引用元包,以便將每個元包繫結到一個目標框架。 例如,netstandard1.6
框架引用NetStandard.Library 1.6.0
版元包。 同樣,netcoreapp2.1
框架引用 Microsoft.NETCore.App 2.1.0
版元包。 有關詳細資訊,請參閱 .NET Core SDK
中的隱式元包引用。
以某個框架為目標以及隱式引用元包,這實際上是新增了對元包中每一個獨立包的引用依賴。 這使這些包中的所有庫都可用於 IntelliSense
(或類似體驗),同時也可用於釋出應用。
使用元包具有以下好處:
- 在引用大量細粒度包方面,提供了一種方便的使用者體驗。
- 定義了一組經過充分測試且執行良好的包(包括指定的各種版本)。
.NET Standard
元包為:
NETStandard.Library
- 描述了屬於“.NET Standard
”一部分的各種庫。 適用於所有支援.NET Standard
的.NET
實現(例如,.NET Framework、.NET Core
和Mono
)。也就是“netstandard
”框架。
重要的 .NET Core
元包有:
Microsoft.NETCore.App
- 描述了屬於.NET Core
發行版的部分庫。 也就是.NETCoreApp 框架
。它依賴於更小的NETStandard.Library
。Microsoft.AspNetCore.App
- 包含來自ASP.NET Core
和Entity Framework Core
的所有受支援的包(包含第三方依賴項的包除外)。 有關詳細資訊,請參閱ASP.NET Core
的Microsoft.AspNetCore.App
元包。Microsoft.AspNetCore.All
- 包含來自ASP.NET Core、Entity Framework Core
以及ASP.NET Core
和Entity Framework Core
使用的內部和第三方依賴項的所有受支援包。 有關詳細資訊,請參閱ASP.NET Core 2.x
的Microsoft.AspNetCore.All
元包。Microsoft.NETCore.Portable.Compatibility
- 一組相容外觀,使基於mscorlib
的可移植類庫(PCL
) 得以在.Net Core
上執行。
框架
每個 .NET Core
包支援一組執行時框架。 框架描述了一組可用的 API
(以及潛在的其他特性),所以你可以在指定一個目標框架時使用這些功能。 新增新的 API
時,它們就會進入版本控制流程。
例如,System.IO.FileSystem
支援以下框架:
- .NETFramework,Version=4.6
- .NETStandard,Version=1.3
- 6 種 Xamarin 平臺(例如,xamarinios10)
將前兩個框架進行對比很有幫助,因為它們各自代表了一種不同的框架定義方式。
.NETFramework,Version=4.6
框架表示 .NET Framework 4.6
中可用的 API
。 你可以生成使用 .NET Framework 4.6
引用程式集編譯的庫,並以NuGet
包的方式在 net46 lib
資料夾中釋出這些庫。 這樣,你的庫就會被那些基於或者相容 .Net Framework 4.6
的應用所使用。 這是所有框架的傳統工作原理。
.NETStandard,Version=1.3
框架是一個基於包的框架。 它依賴基於框架的包,來定義和公開與框架有關的 API
。
基於包的框架
框架和包之間是一種雙向關係。 首先是為一個給定的框架定義了 API
,例如 netstandard1.3
。 以 netstandard1.3
為目標的包(或相容的框架,如 netstandard1.0
)定義了適用於 netstandard1.3
的 API
。 聽起來像是迴圈定義,然而並不是。 從“基於包的”這個詞本身的角度來講,框架的 API
定義是來自於包的。 框架本身並不定義任何 API
。
其次,是這個雙向關係中的資產選擇。 包可以包含多個框架的資產。 對於一組包和/或元包的引用,框架需要決定它應選擇哪些資產,例如,是 net46
還是 netstandard1.3
。 選擇正確的資產很重要。 例如,net46
資產可能並不與 .NET Framework 4.0
或 .NET Core 1.0
相容。
可以在下圖中看到這種關係。 API 選擇框架作為目標並定義了框架。 而框架用於資產選擇。 資產實現了 API
。
在 .Net Core
基礎之上,基於包的框架主要有兩個:
- netstandard
- netcoreapp
.NET Standard
.NET Standard
(目標框架名字物件:netstandard
)框架表示在 .NET Standard
基礎之上生成並由其定義的 API
。 如果構建的庫將用於在多個執行時上執行,就應將此框架作為目標。 這樣便可在任何一種相容 .NET 標準的執行時上受支援,例如 .NET Core、.NET Framework
和 Mono/Xamarin
。 每個執行時都支援一組 .NET Standard
版本,具體取決於實現的 API
。
netstandard
框架隱式引用 NETStandard.Library
元包。 例如,以下 MSBuild
專案檔案指示專案以 netstandard1.6
為目標,其引用 NETStandard.Library 1.6
版元包。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
</Project>
但專案檔案中的框架和元包引用不需要匹配,並且可使用專案檔案中的 <NetStandardImplicitPackageVersion>
元素指定低於元包版本的框架版本。 例如,以下專案檔案有效。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
<NetStandardImplicitPackageVersion>1.6.0</NetStandardImplicitPackageVersion>
</PropertyGroup>
</Project>
面向 netstandard1.3
卻使用 NETStandard.Library 1.6.0
版本,這一點很奇怪。 然而,這是一個有效的用例,因為元包支援更舊的 netstandard
版本。 可能恰好你已將 1.6.0 版的元包進行了標準化,然後將其用於所有庫,而這些庫可以面向各種 netstandard
版本。 使用此方法,只需還原 NETStandard.Library 1.6.0
,無需載入早期版本。
反之,把 netstandard1.6
設為目標,卻使用 1.3.0
版的 NETStandard.Library
也是無效的。 你不能把更高版本的框架設為目標,卻使用更低版本的元包,因為更低版本的元包不會公開任何更高版本框架的資產。 元包資產的版本控制方案與描述框架的最高版本匹配。 藉助於版本控制方案,NETStandard.Library
的第一個版本是 v1.6.0
,因為它包含 netstandard1.6
資產。 而上例中的 v1.3.0
版本,只是為了舉例方便,實際上並不存在。
.NET Core 應用程式
.NET Core
應用程式(目標框架名字物件:netcoreapp
)框架表示 .NET Core
發行版及其提供的控制檯應用程式模型附帶的包和相關 API
。 .NET Core
必須使用此框架,因為必須要使用其中的控制檯應用程式模型。同時只執行於 .Net Core
平臺的庫也應使用此模型。 使用此框架後,所有應用和庫將只能夠在 .Net Core
上執行。
Microsoft.NETCore.App
元包的目標框架是 netcoreapp
。 它提供了約 60 個庫的訪問許可權,其中約 40 個由 NETStandard.Library
包提供,還有另外 20 個庫。 可以引用目標框架為 netcoreapp
或與框架(如 netstandard
)相容的庫獲得對其他 API
的訪問許可權。
由 Microsoft.NETCore.App
提供的大部分其他庫還可以使用 netstandard
作為目標,如果其他 netstandard
庫滿足這些框架的依賴項的話。 這意味著,netstandard
庫也可以引用這些包作為依賴項。
相關文章
- .Net Core 學習筆記1——包、元包、框架筆記框架
- .net core 常用安裝包
- Netty 中的粘包和拆包Netty
- 關於 .NET Core(.NET Core 指南)
- Core Image框架詳細解析(十六) —— 包裝和載入影像單元 Packaging and Loading Image Units...框架
- 開發.NET Core NuGet包並實現CI/CD
- Netty - 粘包與拆包Netty
- Python元組和字典的拆包Python
- JavaScript 閉包基本指南JavaScript
- NET core 釋出時幹掉多餘的語言包-
- Netty入門系列(2) --使用Netty解決粘包和拆包問題Netty
- Netty解決粘包和拆包問題的四種方案Netty
- Burp Suite抓包、截包和改包UI
- 框架庫(.NET 指南)框架
- Netty如何解決粘包拆包?(二)Netty
- Go標準包——net/rpc包的使用GoRPC
- 從零開始netty學習筆記之TCP粘包和拆包Netty筆記TCP
- ASP.NET Core WebApi返回結果統一包裝實踐ASP.NETWebAPI
- net/http包的使用模式和原始碼解析HTTP模式原始碼
- SSM框架各類jar包SSM框架JAR
- PHP 的 JWT 包整理 Hyperf 和傳統 http 框架PHPJWTHTTP框架
- 模組和包
- 通過/proc/net/dev和/proc/net/snmp分析網路包量|流量|錯包|丟包以及各網路協議的工作狀況dev協議
- Android https 抓包指南AndroidHTTP
- RPM包的權威指南。
- 【譯】終極指南:變數提升、作用域和閉包變數
- jar包、war包和ear包的介紹與區別JAR
- 在 ASP.NET Core 專案中使用 npm 管理你的前端元件包ASP.NETNPM前端元件
- Netty拾遺(七)——粘包與拆包問題Netty
- 高仿包和1:1包區別
- oracle dbms包和其他包的使用大全Oracle
- netty 解決粘包 和 分包的問題Netty
- org.springframework.core.styler包解讀SpringFramework
- .NET Protobuf包裝器庫
- net/rpc包的使用RPC
- 【譯】理解JavaScript閉包——新手指南JavaScript
- FOSCommentBundle功能包:指南索引頁索引
- 原始碼包和rpm包的區別原始碼