本文為翻譯文章,原文:Packages, Metapackages and Frameworks
.NET Core是一個由NuGet包組成的平臺。一些產(chǎn)品受益于細粒度包的定義,也有一些受益于粗粒度包的定義。為了適應(yīng)這種二重性,.NET Core平臺被分為一組細粒度的包(package)以及一些被稱為元包(metapackage)的較粗粒度的包。
每一個.NET Core包支持多個.NET運行時,它們代表著不同的框架。這些框架既包括傳統(tǒng)的.NET Framework(如net4.6),也包含基于包的新框架,這些新框架建立了定義框架的新模型。這些基于包的框架完全由包定義而成,包與框架之間形成較強的關(guān)聯(lián)關(guān)系。
包
.NET Core由一組包構(gòu)成,這些包提供了基元類型、高級數(shù)據(jù)類型、應(yīng)用程序組成類型和一些常見的實用工具。每一個包表示一個和包同名的程序集,如, System.Runtime包中含有System.Runtime.dll程序集。
定義細粒度的包有如下好處:
細粒度的包在開發(fā)、測試過程中與其它包的關(guān)聯(lián)有限
細粒度的包可以提供對不同操作系統(tǒng)和CPU的支持
細粒度的包可以只依賴某個特定的庫
在發(fā)布應(yīng)用時,未被引用的包不會成為應(yīng)用的一部分,因此應(yīng)用程序會有更小的體積
有些細粒度包的優(yōu)點只會在特定場景中表現(xiàn)出來。如,通常.NET Core 的所有包會在同一計劃內(nèi)提供對同一平臺的支持。這種情況下,補丁會以小的單個更新包的形式發(fā)布和安裝。由于這種小范圍的變化,驗證補丁是否可用所花費的時間,可以限制到對單個庫的需求中。
下面列出了.NET Core平臺上的一些關(guān)鍵NuGet包:
System.Runtime - 這是最基本的.NET Core包,包括Object, String, Array, Action 和IList<T>.
System.Collections - 表示一組常用泛型集合,包括List<T> 和Dictionary<K,V>.
System.Net.Http - 用于HTTP通訊的類型,包括HttpClient 和HttpResponseMessage.
System.IO.FileSystem -用于讀寫基于磁盤的本地或網(wǎng)絡(luò)存儲類型,包括File和Directory.
System.Linq - 用于查詢對象,包括including Enumerable 和ILookup<TKey, TElement>.
System.Reflection - 用于加載、檢查、創(chuàng)建類型,包括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包約定,用于描述一組放在一起有意義的包。 這些包是通過依賴項來被描述的。可以通過為這組包指定一個框架來建立一個框架(這話拗口,原文:They can optionally establish a framework for this set of packages by specifying a framework.)。
以前版本的.NET Core工具(project.json和基于csproj的工具)在默認情況下會指定一個框架和元包 。不過,現(xiàn)在,元包被目標框架隱式引用,這樣一來每個元包都和目標框架關(guān)聯(lián)在一起。例如,netstandard1.6
框架引用了NetStandard.Library 1.6.0
元包。類似的,netcoreapp1.1
框架引用了Microsoft.NETCore.App 1,1.0
元包。更過信息,參考.NET Core SDK中元包的隱式引用。
指定一個框架會隱式實現(xiàn)對元包引用,同時也會添加對元包依賴項的引用。這樣,元包中的所有類庫都能夠被IDE智能感知,也可以被打包到你的應(yīng)用中。
使用元包有以下好處:
在引用大量細粒度包時有更好的用戶體驗
定義了一組經(jīng)過測試且運行良好的包(包括指定的各種版本)
.NET 標準庫元包(.NET Standard Library metapackage):
-
NETStandard.Library - 表示.NET標準類庫的一部分。所有的.NET 實現(xiàn)(如,.NET Framework、.NET Core 和 Mono)都支持.NET 標準類庫。
NETStandard.Library
用于建立netstandard
框架。
.NET Core核心元包有:
Microsoft.NETCore.App - .NET Core發(fā)行版本類庫的一部分,用于建立 .NETCoreApp框架,它依賴
NETStandard.Library
。Microsoft.NETCore.Portable.Compatibility - 一組基于mscorlib的運行于.NET Core上的可移植類庫
框架
每個.NET Core包都支持多個運行時框架。這些框架描述一組可用于你所指定的框架的API(和一些其它特征)。當加入新的API時,這些框架的版本號也會發(fā)生相應(yīng)的變化。
例如, System.IO.FileSystem 支持以下框架:
- .NETFramework,Version=4.6
- .NETStandard,Version=1.3
- 6 Xamarin platforms (如, xamarinios10)
這些運行時框架使用不同的方式進行框架的定義,對比學(xué)習(xí)前兩個框架會大有裨益。
.NETFramework,Version=4.6
框架表示可用于.NET Framework 4.6之上的API。
我們可以編寫基于.NET Framework 4.6
引用程序集的庫,并以NuGet 包的方式在 net46 lib 文件夾中發(fā)布這些庫。這些庫可用于那些基于或兼容.NET Framework 4.6
的應(yīng)用。這是所有框架的傳統(tǒng)工作方式。
.NETStandard,Version=1.3
是一個基于包的框架。它依靠包來定義目標框架以及公開該框架的API。
基于包的框架
包與框架之間是雙向關(guān)系。首先為一個給定框架定義可用的API,如netstandard1.3
。用于netstandard1.3
框架(或兼容框架,如netstandard1.0
)的軟件包定義該框架上可用的API。這看起來像是循環(huán)定義,但不是。基于包的框架上的API由包來定義,框架本身并不定義任何API。
其次,是這種雙向關(guān)系中的第二部分,資產(chǎn)選擇(asset selection)。包可以包含用于多框架的資產(chǎn)。對于一組包或者元包的引用,框架需要決定選擇哪種資產(chǎn),如net46
或netstandard1.3
。選擇正確的資產(chǎn)是很重要的。如,一個net46
資產(chǎn)可能不兼容.NET Framework 4.0
或 .NET Core 1.0
。

上圖描述了這種雙向關(guān)系。API指定并定義框架。框架選擇資產(chǎn)。資產(chǎn)提供具體的API實現(xiàn)。
.NET Core
平臺上使用的兩個主要的基于包的框架是:
netstandard
netcoreapp
.NET 標準
.NET標準(目標框架名:netstandard)框架是指基于.NET標準庫(.NET Standard Library)而定義和創(chuàng)建的API。這些庫計劃支持以.NET 標準框架為目標框架的多個運行時。它們支持任何與.NET標準(.NET Standard )兼容的運行時,如.NET Core、.NET Framework和Mono/Xamarin(下面附上一張圖作為補充)。每個運行時都支持一組.NET Standard版本,具體取決于它們所要實現(xiàn)的API。
標準框架隱式引用NETStandard.Library
元包。如,下面的MSBuild項目文件顯示了當前項目的目標框架是netstandard1.6
,這個框架引用.NET Standard Library version 1.6
元包。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
</Project>
但是,框架和項目文件中所引用的元包無需一一對應(yīng),你可以在項目文件中使用<NetStandardImplicitPackageVersion>
來制定一個版本號低于元包版本號的框架。如,下面的配置框文件是有效的。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
</PropertyGroup>
<ItemGroup>
<NetStandardImplicitPackageVersion Include="NetStandardLibrary" Version="1.6.0" />
</ItemGroup>
</Project>
netstandard1.3
框架使用NETStandard.Library 1.6.0
可能看起來比較奇怪。但這種使用情況是合法的,因為元包向后兼容低版本的netstandard
。若你已經(jīng)將1.6.0版本的元包并將其應(yīng)用到自己的面向多個netstandard
版本的庫中。通過這種向后兼容的方式,你只需還原(restore)NETStandard.Library1.6.0
而無需關(guān)注更早的版本。
與此相反,netstandard1.6
引用NETStandard.Library 1.3.0
是不被允許的,因為低版本的元包不會公開任何構(gòu)建高版本框架的資產(chǎn)。元包資產(chǎn)的版本控制使得元包和它們所描述的框架的最高版本相匹配。借助版本控制,NETStandard.Library
的第一個版本是1.6.0,它包含netstandard1.6
的資產(chǎn)。上述例子中的1.3.0版本只是為了舉例需要,事實上它并不存在。
.NET Core 應(yīng)用
.NET Core 應(yīng)用(目標框架:netcoreapp)框架表示.NET Core 發(fā)行版和它提供的控制臺應(yīng)用程序模型附帶的包和相關(guān)API。.NET Core應(yīng)用必須使用該框架,因為它基于的控制臺應(yīng)用模型的庫僅僅運行于.NET Core框架上。使用這個框架可以限制應(yīng)用和庫只運行于.NET Core之上。
Microsoft.NETCore.App
元包的目標框架是netcoreapp
。它支持對約60個庫的訪問,其中約40個由NETStandard.Library
提供, 還有約20個其它(標準庫以外的)附加庫。你可以引用基于或兼容netcoreapp
,如netstandard
的附加庫,以獲取對附加庫API的訪問。
大多數(shù)由Microsoft.NETCore.App
提供的附加庫,如果這些庫可以很好的依賴其它的netstandard
庫的話,它們也可用于netstandard
。這意味著netstandard libraries
可以添加對這些包的引用。
結(jié)語
由于水平有限,翻譯內(nèi)容難免有錯誤和不足之處,希望大家提出改進意見。文章最后是自己建立.NET Core控制臺程序的引用包截圖和項目配置文件,大家可以作為輔助理解文章內(nèi)容的補充材料。
項目包引用
項目文件
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Collections.NonGeneric" Version="4.3.0" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.3.0" />
</ItemGroup>
</Project>