.Net Core 中的包、元包与框架(Packages, Metapackages and Frameworks)
包,元包與框架
本文翻譯自?Packages, Metapackages and Frameworks。
.Net Core 是一種由 NuGet 包組成的平臺(tái)。一些產(chǎn)品體驗(yàn)受益于代碼包的細(xì)粒度定義,而另一些受益于粗粒度的定義,這兩種定義都是有用的,不能絕對(duì)地說(shuō)哪個(gè)好與不好。因此,為了適應(yīng)這兩種區(qū)別,一款好的產(chǎn)品應(yīng)該可以被拆分成一組一組的細(xì)粒度的代碼包,這些包之間相互獨(dú)立,單個(gè)代碼包的正式的名字叫做“元包”(metapackage)。
每個(gè).Net Core 包都支持運(yùn)行于多種 .Net 運(yùn)行時(shí)中,這些運(yùn)行時(shí)被稱為 “框架”(framework)。其中有的框架是傳統(tǒng)框架,例如 net46;而另一些則是新的框架,可以認(rèn)為它們是“基于包的框架”,這種是框架的另外一種新的定義模型。這些基于包的框架整個(gè)都是由包組成的,它們自身也被定義成包,這就在框架與包之間形成了一種比較密切的關(guān)系。
包
.Net Core被分割成為一組包,它們提供了基元類型,以及更高層的數(shù)據(jù)類型,應(yīng)用組合類型,以及公共的類庫(kù)。每一個(gè)包都代表著單獨(dú)的同名程序集,例如,System.Runtime 這個(gè)包,就包含了 System.Runtime.dll 這個(gè)程序集。
把這些包定義成為細(xì)粒度的結(jié)構(gòu)風(fēng)格,有以下好處:
- 細(xì)粒度的包可以在它自己的開(kāi)發(fā)周期內(nèi)交付,只需要完成僅對(duì)相關(guān)的其他有限的包進(jìn)行測(cè)試即可。
- 細(xì)粒度的包可以提供不同的OS與CPU支持。
- 細(xì)粒度的包可以單獨(dú)依賴于某一個(gè)類庫(kù)。
- 應(yīng)用可以變得更小,因?yàn)闆](méi)有引用的包不會(huì)變成最終發(fā)布的一部分。
上述好處僅適用于某些特定的場(chǎng)合。比如,Net Core 的所有包會(huì)在同一個(gè)發(fā)布周期內(nèi)提供對(duì)同一個(gè)平臺(tái)的支持,在這種情況下,補(bǔ)丁與更新會(huì)以小的單獨(dú)包的形式發(fā)布。由于這種小范圍的變化,補(bǔ)丁的驗(yàn)證與相關(guān)工作,都可以限制到單個(gè)平臺(tái)與類庫(kù)的需求范圍中,這樣一來(lái),就可以把工作最小化。
以下是 基于 NuGet 庫(kù)的 .Net Core 包清單:
- Sytem.Runtime - 最基礎(chǔ)的 .Net Core 包,包含 Object,String,Array, Action 與 IList<T>。
- System.Collections - 一組基元泛型集合,包含 List<T> 與 Dictionary<K,V>.
- System.Net.Http - 一組用于 HTTP 網(wǎng)絡(luò)通信的類型,包含 HttpClient 與 HttpResponseMessage。
- System.IO.FileSystem - 一組用于讀寫(xiě)本地或者網(wǎng)絡(luò)磁盤(pán)存儲(chǔ)的類型,包含了 File 與 Dictory 類。
- System.Linq - 一組對(duì)象查詢類型,包含了 Enumerable 與 ILookup<TKey, TElement> .
- System.Reflection - 一組用于類型加載,檢查與激活的類型,包含 Assembly, TypeInfo, 與 MethodInfo
包引用在 project.json 文件中定義,在下面的例子中,使用了 System.Runtime 包:
{"dependencies": {"System.Runtime": "4.1.0"},"frameworks": {"netstandard1.5": {}} }
在大部分情況下,你可能不需要直接引用底層的 .Net Core 包,因?yàn)橐玫陌嗔藭?huì)讓你抓狂。所以你只需要引用元包。
元包
元包就是一個(gè) NuGet 包,方便地描述了一組意義相關(guān)的包。開(kāi)發(fā)團(tuán)隊(duì)利用依賴關(guān)系來(lái)描述一組包,他們通過(guò)這一組包來(lái)描述一個(gè)框架(framework),然后有選擇地發(fā)布出去。
引用一個(gè)元包,這個(gè)操作,實(shí)際上添加了對(duì)元包中每一個(gè)獨(dú)立包的引用依賴,這意味著這些包中所有的類庫(kù)(refs 或者 libs)都會(huì)在智能感知(IntelliSense)中可用,同時(shí)也會(huì)發(fā)布(lib目錄)到你的應(yīng)用中。
注意: lib 與 ref 指的是 NuGet 包中的相應(yīng)的文件夾, ref 目錄描述的是以元程序集表示的公共API包,lib 目錄 包含了這個(gè)公共API的在不同框架下的實(shí)現(xiàn)。
使用元包有以下好處:
- 在引用大量細(xì)粒度包方面,提供了一種方便的用戶體驗(yàn)。
- 定義了一組經(jīng)過(guò)充分測(cè)試與工作良好的包(包括指定的各種版本)。
.Net 標(biāo)準(zhǔn)類庫(kù)元包:
- NETStandard.Library - 描述了“.Net 標(biāo)準(zhǔn)類庫(kù)”的一部分。所有的 .Net 實(shí)現(xiàn)(例如, .Net Framework, .Net Core, Mono)都支持 .Net 標(biāo)準(zhǔn)類庫(kù),這就是 'netstandard' 框架。
以下是 .Net Core 元包:
- Microsoft.NETCore.App - 描述了 .Net Core 發(fā)行版本的部分類庫(kù),也就是 .NETCoreApp 框架。它依賴于NETStandard.Library 這個(gè)更小的元包。
- Microsoft.NETCore.Portable.Compatibility - 一組兼容代理,使基于 mscorlib 的 可移植類庫(kù)(PCL) 得以運(yùn)行在 .Net Core上。
元包的引用方法就像普通的 NuGet包一樣,在 project.json 中定義。
在下面的例子中, 引用了 NETStandard.Library 這個(gè)元包,用來(lái)創(chuàng)建一個(gè)基于 .Net 運(yùn)行時(shí)的可移植類庫(kù)。
{"dependencies": {"NETStandard.Library": "1.5.0"},"frameworks": {"netstandard1.5": {}} }
在下面的例子中,引用了 Microsoft.NETCore.App 這個(gè)元包,用來(lái)創(chuàng)建應(yīng)用或者是類庫(kù),運(yùn)行于 .Net Core之上,并且充分使用 .Net Core 所有功能。它提供的訪問(wèn)范圍,要比 NetStandard.Library 更大。
{"dependencies": {"Microsoft.NETCore.App": "1.0.0"},"frameworks": {"netcoreapp1.0": {}} }?
框架
每一個(gè) .Net Core 包都支持一組框架,在框架文件夾中進(jìn)行聲明(就在前面所說(shuō)的 lib 與 ref目錄中)。框架描述了一組可用的API(以及潛在的其他特性),所以你可以在指定一個(gè)目標(biāo)框架時(shí)得到這些功能。當(dāng)新的API加入時(shí),就會(huì)進(jìn)入版本管理流程。
例如, System.IO.FileSystem 支持以下框架:
- .NETFramework,版本 4.6
- .NETStandard,版本 1.3
- 6種Xamarin 平臺(tái) (如, xamarinios10)
很有必要對(duì)前兩種框架進(jìn)行對(duì)比,因?yàn)樗鼈兏髯源砹艘环N不同的框架定義方式。
.NETFramework,Version=4.6 這個(gè)框架代表了在 .Net Framework 4.6 中可用的API,你可以根據(jù)這些API生產(chǎn)自己的類庫(kù),引用其中的程序集,并以NuGet包的方發(fā)布你的類庫(kù),發(fā)布后它們會(huì)位于lib文件夾下一個(gè)名為 net46 的文件夾中。這樣,你的
類庫(kù)就會(huì)被那些基于或者兼容 .Net Framework 4.6 的應(yīng)用程序所使用。這是傳統(tǒng)類庫(kù)的工作方式。
而.NETStandard,Version=1.3這個(gè)框架是一個(gè)基于包的框架。那些以此框架為目標(biāo)的包,定義并且實(shí)現(xiàn)的API,就組成了這個(gè)框架。
可見(jiàn)它們的區(qū)別:傳統(tǒng)的框架是事先定義好的一個(gè)整體,而基于包的框架,則可以對(duì)不同的包自由組合。
基于包的框架
框架與包之間的關(guān)系是雙向的。
首先是為一個(gè)給定的框架定義了一組API,如 netstandard1.3。以 netstandard1.3 為目標(biāo)的包(或者兼容框架,如netstandard1.0)定義了哪些API是可以使用的,聽(tīng)起來(lái)像是循環(huán)定義,然而并不是。從 “基于包的”這個(gè)詞本身的角度來(lái)講,框架的API定義是來(lái)自于包的,框架本身并不定義任何API。
其次,是這個(gè)雙向關(guān)系中的資產(chǎn)選擇。包內(nèi)部可以含有不同框架的資產(chǎn),對(duì)于一組包或者元包的引用,框架需要決定它應(yīng)選擇哪些資產(chǎn),例如,是 net46 還是 netstandard1.3。對(duì)于交叉資產(chǎn)來(lái)說(shuō),這個(gè)非常重要,例如,一個(gè) net46 的資產(chǎn)可能并不會(huì)與 .Net Framework 4.0 或者 .Net Core 1.0 兼容。
你可以在上圖中看到這種關(guān)系,API 選擇 框架 作為目標(biāo),并且API定義了框架, 而框架用于資產(chǎn)選擇,資產(chǎn)實(shí)現(xiàn)了API。
這里出現(xiàn)了一個(gè)有趣的問(wèn)題:框架定義的結(jié)束之處,正是消費(fèi)開(kāi)始的地方。可以把框架看成是由 project.json 文件給出的功能定義,你所依賴的東西創(chuàng)建了實(shí)際上的框架,這個(gè)框架獨(dú)立于那些已經(jīng)發(fā)布出來(lái)的完整框架的依賴項(xiàng)。(譯者注:可以這么理解,
框架的實(shí)際實(shí)現(xiàn)取決于你在 project.json 中引用的東西,可能你并不會(huì)引用所有的包,所以你所依賴的包是官方框架的全部包的一個(gè)子集。)
在.Net Core基礎(chǔ)之上,基于包的框架主要有兩個(gè):
- netstandard
- netcoreapp
.NET Standard
.NET 標(biāo)準(zhǔn)框架(netstandard)意指基于 .Net 標(biāo)準(zhǔn)類庫(kù)所定義與構(gòu)建的API。如果你所構(gòu)建的類庫(kù)將會(huì)用于多種運(yùn)行平臺(tái),應(yīng)該以基于netstandard進(jìn)行構(gòu)建,這樣類庫(kù)就會(huì)支持任何一種 兼容 .Net 標(biāo)準(zhǔn)的運(yùn)行時(shí),比如 .Net Core, .Net Framework以及 Mono/Xamarin。這些運(yùn)行時(shí)中的每一處都支持一種或幾種 .Net 標(biāo)準(zhǔn),至于到底支持哪個(gè)版本,則取決于具體實(shí)現(xiàn)。
元包 NETStandard.Library 的目標(biāo)框架是 netstandard。要以 netstandard 為目標(biāo)框架,最常見(jiàn)的方法是引用此元包。它定義與提供了約40個(gè).Net類庫(kù),并與.Net 標(biāo)準(zhǔn)類庫(kù)所定義的API相關(guān)聯(lián)。你可以引用基于 netstandard 開(kāi)發(fā)的第三方包來(lái)使用第三方API。
一個(gè)給定的 NETStandard.Library 版本,總是與 netstandard 所公開(kāi)的最高版本相匹配。 project.json 文件中對(duì)于框架的引用,主要是用來(lái)從此框架中選擇正確的資產(chǎn)。因此,假如定義了 netstandard1.5,就需要 其中的dll資產(chǎn),而不是 netstandard1.4,或者 net46。
{"dependencies": {"NETStandard.Library": "1.5.0"},"frameworks": {"netstandard1.5": {}} }
這個(gè) project.json 文件中所引用的 框架與元包 并不需要嚴(yán)格匹配,例如下面的 project.json 也是正確的:
{"dependencies": {"NETStandard.Library": "1.5.0"},"frameworks": {"netstandard1.3": {}} }
把構(gòu)建目標(biāo)設(shè)置為 netstandard1.3 卻使用 NETStandard.Library 的 1.5 版本,似乎有點(diǎn)奇怪。然而這是一個(gè)合法的用例,因?yàn)樵С指系?netstandard 版本。可能恰好 你使用了 1.5.0 的元包版本來(lái)開(kāi)發(fā)你所有的類庫(kù),然后運(yùn)行于多種版本的 netstandard,在這種情況下,你只需要重新加載 NETStandard.Library 1.5.0 即可,并不需要加載早期版本。
反之則并不成立:把 netstandard1.5 作為運(yùn)行目標(biāo),卻使用 NETStandard.Library 的 1.3.0 版本來(lái)開(kāi)發(fā)你的類庫(kù):你不能夠把更高版本的框架作為開(kāi)發(fā)目標(biāo),卻使用更低版本的元包。元包資產(chǎn)的版本管理機(jī)制,與框架的最高版本的定義相匹配。借助于版本管理機(jī)制,NETStandard.Library 的第一個(gè)版本是 v1.5.0,它包含了 netstandard1.5 的資產(chǎn)。而上面例子中的 v1.3.0 版本,只是為了舉例方便,實(shí)際上并不存在。
譯者注:這一段的各種名詞相互繞來(lái)繞去,會(huì)把人繞暈。舉個(gè)例子就明白了:因?yàn)轭悗?kù)總是向下兼容的,1.5 的實(shí)現(xiàn)必然包含了1.3的所有定義,1.5 版本的元包,是可以運(yùn)行于 1.3 版本的框架之上。
然而這與我們的直覺(jué)經(jīng)驗(yàn)不符,因此作者說(shuō)看起來(lái)很奇怪,因?yàn)槟阍?Win7 上開(kāi)發(fā)的程序(依賴高版本元包),很可能不支持運(yùn)行在 XP 系統(tǒng)上(低版本框架)。
但是為什么在神奇的 .Net Core 的世界中,這個(gè)現(xiàn)象就發(fā)生了呢?
這是由 .Net Core 的版本管理機(jī)制所決定的。文中并沒(méi)有給出來(lái)具體的解釋。關(guān)于版本管理,有另外一篇文章會(huì)介紹,稍后翻譯。
.NET Core Application
.NET Core Application 框架(netcoreapp) 意為: 包與相關(guān)的API是 基于.Net Core 特定發(fā)布版本以及它所提供的控制臺(tái)程序模型。.Net Core應(yīng)用程序必須使用這個(gè)框架,因?yàn)楸仨氁褂闷渲械目刂婆_(tái)程序模型。同時(shí)只運(yùn)行于 .Net Core 平臺(tái)的類庫(kù)也應(yīng)使用這個(gè)模型。使用這框架以后,應(yīng)用程序(exe)與類庫(kù)(dll)將只能夠運(yùn)行于.Net Core平臺(tái)上。(老外好啰嗦啊) 元包 Microsoft.NETCore.App 的目標(biāo)框架是 netcoreapp 。此元包提供了約 60 個(gè)類庫(kù),其中大約 40 個(gè)是由 NETStandard.Library 提供的,另外20個(gè)是由 Microsoft.NETCore.App 自己實(shí)現(xiàn)的(addition)。如果你開(kāi)發(fā)的類庫(kù)的目標(biāo)框架是 netcoreapp 或其兼容框架(如netstandard),則可以使用 Microsoft.NETCore.App 的這些20個(gè)額外類庫(kù)(addition),來(lái)調(diào)用這些額外的API。
譯注:addition,是指由 Microsoft.NETCore.App 在 NETStandard.Library 基礎(chǔ)之上的額外實(shí)現(xiàn),約20個(gè)類庫(kù)。在從傳統(tǒng) Framework遷移過(guò)來(lái)的代碼中,如果你使用了 NETStandard.Library ,可能會(huì)出現(xiàn)不識(shí)別類或者方法的情況,很有可能是因?yàn)檫@些不識(shí)別的部分實(shí)現(xiàn)在這20個(gè)addition中,改為引用 Microsoft.NETCore.App 可能會(huì)解決問(wèn)題。
由 Microsoft.NETCore.App 額外實(shí)現(xiàn)的大部分類庫(kù),也可以運(yùn)行于 其他的 netstandard 框架,如果這些框架滿足了它們所依賴的類庫(kù)的運(yùn)行環(huán)境的話。這意味著 運(yùn)行于 netstandard 框架的類庫(kù)也引用這些額外包作為依賴項(xiàng)。
譯注:這段話也比較晦澀,再舉例子說(shuō)明。例如 Microsoft.NETCore.App 1.5 (簡(jiǎn)稱App1.5)是 在 NETStandard.Library 1.5 (簡(jiǎn)稱Lib1.5)之上實(shí)現(xiàn)了額外20個(gè)包(Add20),即 App1.5 = Lib1.5 + Add20。 前面說(shuō) Lib1.5 可以運(yùn)行于框架 netstandard 1.5(簡(jiǎn)稱 Std1.5),以及 Std1.3 之上,如果這個(gè) Add20 也可以運(yùn)行于 Lib1.3 的話,那么就可以得到 App1.5 也可以運(yùn)行于 Lib1.3。
轉(zhuǎn)載于:https://www.cnblogs.com/liuweizzuie/p/5827030.html
總結(jié)
以上是生活随笔為你收集整理的.Net Core 中的包、元包与框架(Packages, Metapackages and Frameworks)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 通往奥格瑞玛的道路(洛谷 1462)
- 下一篇: explode() 字符串转换数组