.Net Core 中的包、元包與框架(Packages, Metapackages and Frameworks)

包,元包與框架

本文翻譯自 Packages, Metapackages and Frameworksjavascript

.Net Core 是一種由 NuGet 包組成的平臺。一些產品體驗受益於代碼包的細粒度定義,而另外一些受益於粗粒度的定義,這兩種定義都是有用的,不能絕對地說哪一個好與很差。所以,爲了適應這兩種區別,一款好的產品應該能夠被拆分紅一組一組的細粒度的代碼包,這些包之間相互獨立,單個代碼包的正式的名字叫作「元包」(metapackage)。java

每一個.Net Core 包都支持運行於多種 .Net 運行時中,這些運行時被稱爲 「框架」(framework)。其中有的框架是傳統框架,例如 net46;而另外一些則是新的框架,能夠認爲它們是「基於包的框架」,這種是框架的另一種新的定義模型。這些基於包的框架整個都是由包組成的,它們自身也被定義成包,這就在框架與包之間造成了一種比較密切的關係。ios

.Net Core被分割成爲一組包,它們提供了基元類型,以及更高層的數據類型,應用組合類型,以及公共的類庫。每個包都表明着單獨的同名程序集,例如,System.Runtime 這個包,就包含了 System.Runtime.dll 這個程序集。json

把這些包定義成爲細粒度的結構風格,有如下好處:網絡

  • 細粒度的包能夠在它本身的開發週期內交付,只須要完成僅對相關的其餘有限的包進行測試便可。
  • 細粒度的包能夠提供不一樣的OS與CPU支持。
  • 細粒度的包能夠單獨依賴於某一個類庫。
  • 應用能夠變得更小,由於沒有引用的包不會變成最終發佈的一部分。

上述好處僅適用於某些特定的場合。好比,Net Core 的全部包會在同一個發佈週期內提供對同一個平臺的支持,在這種狀況下,補丁與更新會以小的單獨包的形式發佈。因爲這種小範圍的變化,補丁的驗證與相關工做,均可以限制到單個平臺與類庫的需求範圍中,這樣一來,就能夠把工做最小化。app

如下是 基於 NuGet 庫的 .Net Core 包清單:框架

  • Sytem.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 - 一組用於讀寫本地或者網絡磁盤存儲的類型,包含了 File 與 Dictory 類。
  • System.Linq - 一組對象查詢類型,包含了 Enumerable 與 ILookup<TKey, TElement> .
  • System.Reflection - 一組用於類型加載,檢查與激活的類型,包含 Assembly, TypeInfo, 與 MethodInfo

包引用在 project.json 文件中定義,在下面的例子中,使用了 System.Runtime 包:測試

{
 "dependencies": {
    "System.Runtime": "4.1.0"
  },
  "frameworks": {
    "netstandard1.5": {}
  }
}

  

在大部分狀況下,你可能不須要直接引用底層的 .Net Core 包,由於引用的包太多了會讓你抓狂。因此你只須要引用元包。spa

元包

元包就是一個 NuGet 包,方便地描述了一組意義相關的包。開發團隊利用依賴關係來描述一組包,他們經過這一組包來描述一個框架(framework),而後有選擇地發佈出去。翻譯

引用一個元包,這個操做,實際上添加了對元包中每個獨立包的引用依賴,這意味着這些包中全部的類庫(refs 或者 libs)都會在智能感知(IntelliSense)中可用,同時也會發布(lib目錄)到你的應用中。

注意: lib 與 ref 指的是 NuGet 包中的相應的文件夾, ref 目錄描述的是以元程序集表示的公共API包,lib 目錄 包含了這個公共API的在不一樣框架下的實現。

使用元包有如下好處:

  • 在引用大量細粒度包方面,提供了一種方便的用戶體驗。
  • 定義了一組通過充分測試與工做良好的包(包括指定的各類版本)。

.Net 標準類庫元包:

  • NETStandard.Library - 描述了「.Net 標準類庫」的一部分。全部的 .Net 實現(例如, .Net Framework, .Net Core, Mono)都支持 .Net 標準類庫,這就是 'netstandard' 框架。

如下是 .Net Core 元包:

  • Microsoft.NETCore.App - 描述了 .Net Core 發行版本的部分類庫,也就是 .NETCoreApp 框架。它依賴於NETStandard.Library 這個更小的元包。
  • Microsoft.NETCore.Portable.Compatibility - 一組兼容代理,使基於 mscorlib 的 可移植類庫(PCL) 得以運行在 .Net Core上。

元包的引用方法就像普通的 NuGet包同樣,在 project.json 中定義。

在下面的例子中, 引用了 NETStandard.Library 這個元包,用來建立一個基於 .Net 運行時的可移植類庫。

{
  "dependencies": {
    "NETStandard.Library": "1.5.0"
  },
  "frameworks": {
    "netstandard1.5": {}
  }
}

  

在下面的例子中,引用了 Microsoft.NETCore.App 這個元包,用來建立應用或者是類庫,運行於 .Net Core之上,而且充分使用 .Net Core 全部功能。它提供的訪問範圍,要比 NetStandard.Library 更大。

{
  "dependencies": {
    "Microsoft.NETCore.App": "1.0.0"
  },
  "frameworks": {
    "netcoreapp1.0": {}
  }
}

 

框架

每個 .Net Core 包都支持一組框架,在框架文件夾中進行聲明(就在前面所說的 lib 與 ref目錄中)。框架描述了一組可用的API(以及潛在的其餘特性),因此你能夠在指定一個目標框架時獲得這些功能。當新的API加入時,就會進入版本管理流程。

例如, System.IO.FileSystem 支持如下框架:

  • .NETFramework,版本 4.6
  • .NETStandard,版本 1.3
  • 6種Xamarin 平臺 (如, xamarinios10)

頗有必要對前兩種框架進行對比,由於它們各自表明了一種不一樣的框架定義方式。

.NETFramework,Version=4.6 這個框架表明了在 .Net Framework 4.6 中可用的API,你能夠根據這些API生產本身的類庫,引用其中的程序集,並以NuGet包的方發佈你的類庫,發佈後它們會位於lib文件夾下一個名爲 net46 的文件夾中。這樣,你的

類庫就會被那些基於或者兼容 .Net Framework 4.6 的應用程序所使用。這是傳統類庫的工做方式。

而.NETStandard,Version=1.3這個框架是一個基於包的框架。那些以此框架爲目標的包,定義而且實現的API,就組成了這個框架。

可見它們的區別:傳統的框架是事先定義好的一個總體,而基於包的框架,則能夠對不一樣的包自由組合。

基於包的框架

框架與包之間的關係是雙向的。

首先是爲一個給定的框架定義了一組API,如 netstandard1.3。以 netstandard1.3 爲目標的包(或者兼容框架,如netstandard1.0)定義了哪些API是可使用的,聽起來像是循環定義,然而並非。從 「基於包的」這個詞自己的角度來說,框架的API定義是來自於包的,框架自己並不定義任何API。

其次,是這個雙向關係中的資產選擇。包內部能夠含有不一樣框架的資產,對於一組包或者元包的引用,框架須要決定它應選擇哪些資產,例如,是 net46 仍是 netstandard1.3。對於交叉資產來講,這個很是重要,例如,一個 net46 的資產可能並不會與 .Net Framework 4.0 或者 .Net Core 1.0 兼容。


你能夠在上圖中看到這種關係,API 選擇 框架 做爲目標,而且API定義了框架, 而框架用於資產選擇,資產實現了API。

這裏出現了一個有趣的問題:框架定義的結束之處,正是消費開始的地方。能夠把框架當作是由 project.json 文件給出的功能定義,你所依賴的東西建立了實際上的框架,這個框架獨立於那些已經發布出來的完整框架的依賴項。(譯者注:能夠這麼理解,

框架的實際實現取決於你在 project.json 中引用的東西,可能你並不會引用全部的包,因此你所依賴的包是官方框架的所有包的一個子集。)

在.Net Core基礎之上,基於包的框架主要有兩個:

  • netstandard
  • netcoreapp

.NET Standard

.NET 標準框架(netstandard)意指基於 .Net 標準類庫所定義與構建的API。若是你所構建的類庫將會用於多種運行平臺,應該以基於netstandard進行構建,這樣類庫就會支持任何一種 兼容 .Net 標準的運行時,好比 .Net Core, .Net Framework以及 Mono/Xamarin。這些運行時中的每一處都支持一種或幾種 .Net 標準,至於到底支持哪一個版本,則取決於具體實現。

元包 NETStandard.Library 的目標框架是 netstandard。要以 netstandard 爲目標框架,最多見的方法是引用此元包。它定義與提供了約40個.Net類庫,並與.Net 標準類庫所定義的API相關聯。你能夠引用基於 netstandard 開發的第三方包來使用第三方API。

一個給定的 NETStandard.Library 版本,老是與 netstandard 所公開的最高版本相匹配。 project.json 文件中對於框架的引用,主要是用來今後框架中選擇正確的資產。所以,假如定義了 netstandard1.5,就須要 其中的dll資產,而不是 netstandard1.4,或者 net46。

{
 "dependencies": {
   "NETStandard.Library": "1.5.0"
 },
 "frameworks": {
   "netstandard1.5": {}
 }
}

  

這個 project.json 文件中所引用的 框架與元包 並不須要嚴格匹配,例以下面的 project.json 也是正確的:

{
 "dependencies": {
   "NETStandard.Library": "1.5.0"
 },
 "frameworks": {
   "netstandard1.3": {}
 }
}

  

把構建目標設置爲 netstandard1.3 卻使用 NETStandard.Library 的 1.5 版本,彷佛有點奇怪。然而這是一個合法的用例,由於元包支持更老的 netstandard 版本。可能剛好 你使用了 1.5.0 的元包版原本開發你全部的類庫,而後運行於多種版本的 netstandard,在這種狀況下,你只須要從新加載 NETStandard.Library 1.5.0 便可,並不須要加載早期版本。

反之則並不成立:把 netstandard1.5 做爲運行目標,卻使用 NETStandard.Library 的 1.3.0 版原本開發你的類庫:你不可以把更高版本的框架做爲開發目標,卻使用更低版本的元包。元包資產的版本管理機制,與框架的最高版本的定義相匹配。藉助於版本管理機制,NETStandard.Library 的第一個版本是 v1.5.0,它包含了 netstandard1.5 的資產。而上面例子中的 v1.3.0 版本,只是爲了舉例方便,實際上並不存在。

譯者注:這一段的各類名詞相互繞來繞去,會把人繞暈。舉個例子就明白了:由於類庫老是向下兼容的,1.5 的實現必然包含了1.3的全部定義,1.5 版本的元包,是能夠運行於 1.3 版本的框架之上。

然而這與咱們的直覺經驗不符,所以做者說看起來很奇怪,由於你在 Win7 上開發的程序(依賴高版本元包),極可能不支持運行在 XP 系統上(低版本框架)。

可是爲何在神奇的 .Net Core 的世界中,這個現象就發生了呢?

這是由 .Net Core 的版本管理機制所決定的。文中並無給出來具體的解釋。關於版本管理,有另一篇文章會介紹,稍後翻譯。

.NET Core Application

.NET Core Application 框架(netcoreapp) 意爲: 包與相關的API是 基於.Net Core 特定發佈版本以及它所提供的控制檯程序模型。.Net Core應用程序必須使用這個框架,由於必需要使用其中的控制檯程序模型。同時只運行於 .Net Core 平臺的類庫也應使用這個模型。使用這框架之後,應用程序(exe)與類庫(dll)將只可以運行於.Net Core平臺上。(老外好囉嗦啊) 元包 Microsoft.NETCore.App 的目標框架是 netcoreapp 。此元包提供了約 60 個類庫,其中大約 40 個是由 NETStandard.Library 提供的,另外20個是由 Microsoft.NETCore.App 本身實現的(addition)。若是你開發的類庫的目標框架是 netcoreapp 或其兼容框架(如netstandard),則可使用 Microsoft.NETCore.App 的這些20個額外類庫(addition),來調用這些額外的API。

譯註:addition,是指由 Microsoft.NETCore.App 在 NETStandard.Library 基礎之上的額外實現,約20個類庫。在從傳統 Framework遷移過來的代碼中,若是你使用了 NETStandard.Library ,可能會出現不識別類或者方法的狀況,頗有多是由於這些不識別的部分實如今這20個addition中,改成引用 Microsoft.NETCore.App 可能會解決問題。

由 Microsoft.NETCore.App 額外實現的大部分類庫,也能夠運行於 其餘的 netstandard 框架,若是這些框架知足了它們所依賴的類庫的運行環境的話。這意味着 運行於 netstandard 框架的類庫也引用這些額外包做爲依賴項。

譯註:這段話也比較晦澀,再舉例子說明。例如 Microsoft.NETCore.App 1.5 (簡稱App1.5)是 在 NETStandard.Library 1.5 (簡稱Lib1.5)之上實現了額外20個包(Add20),即 App1.5 = Lib1.5 + Add20。 前面說 Lib1.5 能夠運行於框架 netstandard 1.5(簡稱 Std1.5),以及 Std1.3 之上,若是這個 Add20 也能夠運行於 Lib1.3 的話,那麼就能夠獲得 App1.5 也能夠運行於 Lib1.3。

相關文章
相關標籤/搜索