.NET 新標準介紹

本文介紹如何使用 .NET 標準,更容易地實現向 .NET Core 遷移。文中會討論計劃包含的 APIs,跨構架兼容性如何工作以及這對 .NET Core 意味着什麼。

如果你對細節感興趣,這篇文章正是爲你準備的;如果你沒有那麼多時間或者對細節並不感興趣,你可以僅僅只閱讀 TL;DR 章節。

 

TL;DR

對於跨平臺的 .NET 開發者來說,.NET 標準解決了編碼共享的問題。.NET 標準帶來了所有你所需要的和期待的,跨環境的 APIs:桌面應用,移動應用/遊戲和雲服務。

  • .NET 標準是一組所有 .NET 平臺必須實現的 APIs。這就統一了 .NET 平臺並防止平臺在未來分離。
  • .NET 2.0 標準將由 .NET 框架,.NET Core 和 Xamarin 來實現。對於 .NET Core,這將會增加許多現有的被期待的 APIs。
  • 對於 .NET Framework 的二進制文件,.NET 2.0 標準包含了一個兼容性的功能,顯著地增加庫類集,這個你可以參考 .NET 標準庫。
  • .NET 標準將取代便攜式類庫(PCLs)作爲構建多平臺 .NET 庫的工具集。
  • 你可以看到 .NET APIs 標準定義在 dotnet/standard GitHub 上,同時這也以在 GitHub 上獲得。

 

爲什麼我們需要一個標準?

在文章中的介紹 .NET Core 部分會詳細解釋,.NET 平臺已經分離開很多年了。

一方面,這其實是一個很好的事情。它允許根據需求來裁剪 .NET,這是一個單平臺做不到的。例如,.NET Compact Framework 的創建是爲了適應2000年代手機發展的足跡。今天同樣也是這樣:統一集合運行在20多個平臺上。對於任何期待的技術來說,能夠分離和定製是一項很重要的能力。

但另一方面,平臺分離也給 .NET 多平臺的開發者編寫代碼帶來了很大的問題,因爲沒有一個統一的庫類來使用:

目前 .NET 有三種主要的風格,這意味着你必須要掌握三種不同的基類庫,來編寫跨三種風格的代碼。比起 .NET 被創立之初時,現狀已變得更加的多樣。微軟或者其它人將會創建新的 .NET 風格,來支持新的操作系統或者裁剪 .NET 來適應特殊設備的兼容。

 

.NET標準產生的原因:

對於開發者來說,這意味着他們只需要掌握一個基礎類庫。針對 .NET 標準的庫類,將能夠在所有的 .NET 平臺上運行。平臺提供者不需要再猜測他們需要提供哪些 APIs ,來對應 NuGet 上獲取的庫類。

  • 應用。在應用程序方面你不需要直接使用 .NET 標準。不過,你還會間接地受益。首先,.NET 標準會確保所有的 .NET 平臺共享具有相同 APIs 的基礎類庫。一旦你學會了如何在桌面應用程序中使用它,你知道如何在移動應用程序或雲服務中使用它。其次,.NET 標準中的大部分類庫會變得隨處可見,這意味着基礎層的一致性也將適用於更大規模的 .NET 庫生態系統。
  • 便攜式類庫。讓我們來和便攜式類庫(PCLs)如何工作做個對比。使用 PCLs,你可以選擇你想要運行的平臺,同時你也可以選用的 APIs 呈現給你的工具。因此,當工具幫助生成了能在多平臺上運行的二進制文件時,它也會迫使你去考慮不同的基礎庫類。使用 .NET 標準,你有一個單一的基礎類庫。庫類中的所有,將會在全部的 .NET 平臺中獲得支持--那些當前的以及未來的。另一個重要方面是,.NET 標準的 APIs 的可用性是可預測的:高版本意味着更多的 APIs。使用 PCLs,以下情況不是必然的:一組可用的 APIs ,這將是所選擇的平臺之間的交集。
  • 一致性的APIs 。如果你比較. NET 框架、.NET Core和Xamarin/Mono,你會發現 .NET Core 提供了最小的 APIs 界面(不含特定操作系統的 APIs )。第一個問題是基礎性的 APIs 的可用性有大幅差異(如 networking 和加密的 APIs )。第二個問題 .NET Core 的引入在 APIs 方面有很大的不同,尤其是在反應方面。這兩個問題是將代碼移植到 .NET Core 上很難的主要原因。通過創建 .NET 標準,我們正在設定具有跨所有 .NET 平臺的一致性 APIs 的要求,這也包括可用性和 APIs 的形式。
  • 版本控制和工具。正如我在介紹 .NET Core 時提到的,我們的目標是爲了奠定一個便攜式 .NET 平臺的基礎,這樣就可以統一 APIs 的信息和實現。我們預計它會成爲下一個便攜式庫類的版本。不幸的是,它沒有以一個巨大的工具體驗作爲結果。由於我們的目標是代表任何 .NET 平臺,我們不得不將它分解成更小的 NuGet 包。如果所有這些組件都可以部署到應用程序上,那麼將會工作得很好,這樣你也可以獨立的更新他們。但是,如果針對的是抽象的規範,例如像 PCLs 或者 .NET 標準,這將不會工作的很好。因爲有一套非常具體的組合版本,來確保能夠在正確的平臺上運行。爲了避免這個問題,我們定義了 .NET 標準作爲一個單獨的 NuGet 包。因爲它僅表示必需那組 APIs,也沒有將它繼續分解的必要,因爲所有 .NET 平臺必須以所有的方式支持它。唯一重要的方面是它的版本,它扮演的像一個 APIs 的等級:較高的版本,有更多的 APIs ,但較低的版本,更多的 .NET 平臺已經實現了它。

總而言之,我們需要 .NET 標準,原因有二:

  1. 驅動力的一致性。我們希望擁有一套需求一致的,在所有的 .NET 平臺上都實現了的 APIs ,來獲得 .NET 庫的生態系統的訪問。
  2. 跨平臺工具的基礎。我們希望有一個簡單的工具體驗,允許通過選擇一個單獨的版本號,來制定所有 .NET 平臺的公共的目標。

 

.NET 2.0 標準有哪些新功能?

當我們發佈 .NET Core 1.0 時,我們還推出了 .NET 標準。還有很多個 .NET 標準的版本,來表示跨當前所有平臺的 APIs 的可用性。下表顯示了一個現有的平臺的版本,與 .NET 標準的一個給定版本的兼容:

.NET平臺

.NET標準

 

1.0

1.1

1.2

1.3

1.4

1.5

1.6

2.0

.NET Core

1.0

vNext

.NET框架

4.5

4.5.1

4.6

4.6.1

4.6.2

vNext

4.6.1

Xamarin.iOS

vNext

Xamarin.Android

vNext

通用的Windows平臺

10.0

vNext

視窗

8

8.1

         

Windows手機

8.1

         

Windows Phone的Silverlight的

8

             

箭頭表示,該平臺支持更高版本的 .NET 標準。例如,.NET Core 1.0 支持 .NET 標準1.6版,這就是爲什麼有指向的較低版本1.0 - 1.5的右箭頭。

你可以藉此來了解 .NET 標準的最高版本,以便根據你計劃運行的 .NET 平臺,更有針對性的選擇。舉例來說,如果你想在 .NET Framework  4.5 和 .NET Core 1.0 上運行,你可以最多可以選擇 .NET 標準1.1。

您還可以看到哪些平臺將支持 .NET 2.0 標準:

  • 我們將會更新 .NET Core,Xamarin 和 UWP 的版本,這樣將會添加所有支持 .NET 2.0 標準的必要的 APIs。
  • .NET Framework 4.6.1已經實現了所有的 APIs,這也是 .NET 2.0 標準的一部分。需要注意的是這個版本出現了兩次; 後來我將介紹這是爲什麼以及它是如何工作的。

.NET 標準也與便攜式類庫兼容。從 PCLs 屬性到 .NET 標準版本的映射列在我們的文檔。

從一個目標 .NET 標準庫類中,你就可以引用兩個其它的類庫:

  • .NET 標準,如果它們的版本是低於或等於你的目標版本。
  • 便攜式類庫,如果它們的屬性可以映射到一個版本低於或等於你的目標版本的 .NET 標準版本。

從圖形上看,就像這樣:

不幸的是,NuGet 上 PCLs 和 .NET 標準的採用,並不是那麼高。這是一個給定的目標包中有多少次發生在 NuGet.org:

目標

出現次數

.NET框架

46894

.NET標準

1886

 Portable

4501

正如你所看到的,這是很清楚, NuGet 上的絕大多數的類庫,都是以 .NET 框架爲目標的。但是,我們也知道那些庫類中的很大一部分,都只使用了我們在 .NET2.0 標準中提供的 APIs。

在 .NET 2.0 標準中,我們將有可能使用以 .NET 標準爲目標的庫類,同樣也可以通過兼容性的功能,實現現有的 .NET框架二進制文件的引用:

當然,這只是在 .NET 框架庫使用 .NET 標準中可用的 APIs 時,纔會起作用。這就是爲什麼這不是首選方式,來創建跨不同的 .NET 平臺使用的庫。然而,這種兼容性功能提供了一個橋樑,使你可以轉換庫類到 .NET 標準,而不必放棄那些沒有被轉換,卻還在引用的現有庫類。

如果您想了解更多關於兼容性功能是如何工作的,請看的規範 .NET 2.0 標準。

 

.NET 2.0 標準的重大更改:添加的 .NET Framework 4.6.1 的兼容性

一個標準只有當平臺實現時纔有用。與此同時,我們也希望使得 .NET 標準有用並有意義,這是因爲對以標準爲目標的庫類來說,這些 APIs 是可以用的:

  • .NET 框架。.NET FrameWork 4.6.1具有最高的採用,這使得它成爲了最吸引人的 .NET 框架版本。因此,我們要確保它可以在 .NET 2.0 標準中實現。
  • .NET Core。如上所述,.NET Core 擁有小得多的 APIs 集,對比於 .NET 框架和 Xamarin。支持 .NET 2.0 標準意味着我們需要顯著增加界面。由於 .NET Core 不與操作系統配套,但與應用程序配套,所以支持 .NET 2.0 標準只需要更新 SDK 和 NuGet 包。
  • Xamarin。Xamarin 已經支持大部分的 APIs,這些 APIs 也是 .NET 標準的一部分。更新的工作原理類似於 .NET Core --我們希望可以更新到包含所有 APIs 的 Xamarin。事實上,APIs 中的絕大多數,已經加入到穩定的 Cycle 8 release/Mono 4.6.0 中了。

下面列出了支持.NET標準的 .NET Framework 版本:

 

1.4

1.5

1.6

2.0

.NET Framework 

4.6.1

4.6.2

vNext

4.6.1

爲了讓 .NET FrameWork  4.6.1 支持 .NET 2.0 標準,我們不得不刪除所有的 .NET 標準中引入的 APIs。緊隨普通版本規則之後,可以預料,.NET 2.0 標準將只會被一個更新的 .NET Framework 所支持。考慮到 .NET FrameWork  4.6.2 的最新版本只支持 .NET 1.5 標準。這意味着,針對 .NET 2.0 標準編制的庫,不會運行在絕大多數 .NET 框架的安裝上。 

你可能想知道這一決定帶來的影響是什麼。我們針對 .NET1.5 標準和更高的版本,使用所有的 APIs 在 NuGet.org 上對所有的包,進行分析。在寫這篇文章的時候,只發現了6個非微軟的包做到這一點。我們會接觸到這些包的擁有者,並與他們合作,以解決這個問題。從看它們的用來看途,很顯然,他們的調用能夠被 .NET 2.0 標準的 APIs 所代替。

爲了使這些包能支持 .NET 1.5 標準,1.6 和 2.0,他們需要針對這些版本進行交叉編譯。或者,他們可以選擇對 .NET2.0 標準或更高版本給予廣泛平臺的支持。

 

.NET標準有什麼?

爲了決定哪些 APIs 會成爲 .NET 標準的一部分,我們使用下面的方法:

  • 輸入。我們是以所有 .NET 框架和 Xamarin 中可用的 APIs 開始的。
  • 評估。我們所有的這些 APIs 分爲兩個部分:
  1. 必需。我們希望所有的平臺都提供,並且我們相信的可以實現跨平臺的 APIs,我們將此視爲必需。
  2. 可選。特殊平臺或者屬於傳統技術的一部分的 APIs,我們將此視爲可選。

可選 APIs 不是 .NET 標準的一部分,但可作爲單獨的 NuGet 包。我們嘗試針對 .NET 標準,作爲庫類創建他們,以至於他們的實現可以根據平臺的不同而定製,但對於平臺特殊的 APIs,這不總是可行的。

爲了使一些 APIs 可選,我們不得不刪除這是必需 APIs 集的一部分其他 APIs。例如,我們決定在 .NET 標準中具有 AppDomain,而代碼訪問安全性(CAS)是一個傳統部件。這就要求我們刪除 AppDomain 中使用 CAS 類型包含的所有成員,如創建域中的重載。

.NET 標準 APIs 集,以及我們可選 APIs 的提議,將會被 .NET 標準的審查機構審閱。

這裏是 .NET 2.0 標準的 APIs 界面的高度概括:

 

如果你想看看 .NET 2.0 標準特定的 APIs 集,你可以看看 .NET 標準 GitHub 的信息庫。請注意,.NET 2.0 標準是一項正在進行的工作,這意味着一些 APIs 可能會增加,而另一些可能會被刪除。

 

我們還可以使用特定平臺的 APIs 嗎?

創建多平臺庫類的經驗中的一個最大挑戰,就是避免只有大衆化的東西,同時確保你不會意外地創建原本不打算創建的庫類。

在 PCLs,我們通過擁有多個配置文件(其中每一個代表着一套平臺的交集),解決了這個問題。這樣做的好處是,允許你在一組目標之間,最大輸出該 APIs 界面。.NET 標準代表了所有 .NET 平臺必須要實現的一組 APIs。

這也帶來了問題,那就是如何定義那些無法在全部平臺上實現的 APIs:

  • 運行時特定APIs。例如,運用反射發出生成和運行代碼的能力。因爲沒有一個 JIT 編譯器,所以這是不能在 .NET 平臺上起作用的,如 UWP 上的 .NET 原生或 Xamarin 的 iOS 工具鏈。
  • 操作系統特定APIs。在 .NET 中,我們已經從 Win32 中暴露了許多 APIs,以使他們能夠更容易被使用。一個很好的例子就是 Windows 註冊表。實現依賴於在其他操作系統上不具備的等同的底層 Win32 APIs 。

對於這些APIs,我們有以下的選項:

  1. 使得APIs 不可用。不能使用不能在跨所有 .NET 平臺上工作的 APIs 。
  2. 使得APIs 可用,但卻丟棄PlatformNotSupportedException。這意味着不論它們是否是支持或不支持,我們將會公開所有的 APIs 。不支持它們的平臺會提供 APIs ,但是會丟棄 PlatformNotSupportedException。
  3. 模擬APIs 。Mono 作爲一個 APIs 通過 APIs  .ini 文件,實現了註冊表。這雖然對於使用註冊表來讀取操作系統信息的應用不起作用,但是對於簡單的使用註冊表,來存儲自己狀態和用戶設置的應用來說,卻起了很好的作用。

我們相信,最好的選擇是一個組合。正如上面提到的,我們希望 .NET 標準代表一組所有 .NET 平臺都要求實現的 APIs。我們要讓這個設定合理地實施,同時確保流行的 APIs 也都存在,這樣編寫跨平臺的庫會非常簡單,直觀。

解決只在一些 .NET 平臺可用的技術的一般策略是:提供給他們 .NET 標準上的 NuGet 包。所以,如果你創建一個基於 .NET 標準的庫時,它會默認不引用這些 APIs 。你必須添加一個 NuGet 包進來。

對於自包含的並且可以整理成獨立包的 APIs 來說,這種策略工作得很好。對於單個類型成員不能在所有環境下實現的情況,我們將使用第二和第三種方法:平臺必須有這些成員,但他們可以決定丟棄或模仿他們。

讓我們看幾個例子,瞭解我們是計劃如何模擬它們:

  • 註冊。Windows 註冊表是一個自包含的控件,將作爲一個單獨的 NuGet 包被提供。你可以從 .NET Core 中使用它,但它只能在 Windows 上運行。從任何其他操作系統調用 APIs 的註冊表,將會導致 PlatformNotSupportedException。你希望適當地保護你的調用或者確保你的代碼只運行在 Windows 上。我們正在考慮改善我們的工具,來幫助你檢測這些情況。
  • AppDomain。該 AppDomain 類型有很多的 APIs ,不依賴於創建應用程序域,如獲取加載的程序集列表或登記未處理的異常處理。這些 APIs 是整個 .NET 庫生態系統中大量使用的。對於這種情況,我們決定添加這種類型到 .NET 標準,讓少量的 APIs 來應對平臺上應用程序域創建時,不支持拋出的異常要好的多,如 .NET Core。
  • 反射發出。反射發出是合理的自包含。因此,我們計劃按照模型進行註冊。有一個另外的 APIs 邏輯上依賴於 emit 代碼,例如表達式樹形的編譯或者編譯正則表達式的能力。在某些情況下,我們會模仿他們的行爲,而在其他情況下,我們會丟棄。

一般情況下,就像你今天做的,你可以通過以特殊 .NET 平臺爲目標,使用 .NET 標準中還沒可用的 APIs 工作。我們正在考慮如何才能改善我們的工具,來幫助特殊平臺與位置平臺之間遷移地更加流暢,你可以根據你的情境做出最好的選擇,不必考慮早先設計的選擇。

總結:

  • 我們將揭露一些並不適用於所有.NET平臺的概念。
  • 我們將會讓他們成爲你必須明確引用的獨立的包。
  • 在極少數情況下,個別成員可能會拋出異常。

我們的目標是讓 .NET 基礎標準庫儘可能強大的並具有表現力,同時讓你瞭解到你所依賴的技術並不是在任何環境下都起作用。

 

.NET Core意味着什麼?

我們設計 .NET Core,是爲了它的引用程序集是 .NET 可移植的。這使得它很難增加新的 APIs ,因爲在 .NET Core 中添加這些 APIs,取代了決定這些 APIs 是否在任何環境下都可用。更糟的是,由於版本規則,這也意味着我們必須決定哪些 APIs 的組合在老版本中是可用的。

  • 帶外數據遞送。我們試圖通過這些可用 APIs 來解決這個帶外數據,這意味着要做出新的可以安置在現有 APIs 頂端的組件。對於技術,這是容易做到的,也是首選的方法,因爲這也意味着任何 .NET 開發人員可以使用這些 APIs 並且給我們反饋。對於這些不可改變的集合,我們已經做出了巨大的成功。
  • 運行時啓示功能。但是,對於需要運行時工作的特性,這是更難的,因爲我們不能只給你一個起作用的 NuGet 包。我們必須給你一種方式來獲得一個更新的運行時。這對具有全系統運行時的平臺,這個更難。因爲對於不同的目的,我們有多種運行時。這是不實際的,一次跨越所有範圍去創新。有關 .NET Core 的好處是,這個平臺的設計是完全獨立的。因此,對於未來,我們就更有可能將此功能用於實驗和預覽。
  • 從.NET Core拆分.NET標準。爲了能夠從其他 .NET 平臺獨立地發展 .NET Core,我們已經從 .NET Core 分析了便攜性機制。.NET 標準被定義爲滿足所有的 .NET 平臺的一個獨立引用集合。每 .NET 平臺使用一套不同的引用程序集,因此可以自由地在他們選擇的部分增添新的 APIs。然後我們也可以決定向 .NET 標準添加哪些 APIs,讓其成爲通用的。

從 .NET Core 中分離便攜性,幫助我們加快 .NET Core 的發展,使得新特性的實驗更加的容易。除了人工設計位於現存平臺頂端的特性,我們可以簡單的修改底層,以便支持這個特性。我們還可以將 APIs 添加到邏輯上歸屬的類型中,而不必擔心類型是否已經在其它平臺上拓展過。

給 .NET Core 中添加新的 APIs 已經不是一個陳述了,我們對 .NET 標準的目標,是創造 .NET 平臺之間的一致性,所以新的類型成員成爲標準的一部分,在標準更新時已經被自動考慮了。

 

作爲一個庫類開發者,你可以做些什麼?

作爲一個庫類開發者,你應該考慮切換到 .NET 標準,因爲以多 .NET 平臺爲目標,它會取代便攜式庫類。

在 .NET 1.x 標準下,可用的 APIs 集合與 PCLs 非常相似。但是,.NET 2.x 標準將會有更大的 APIs 集,這也允許你依賴於 .NET 框架的庫類。

PCLs和 .NET 標準之間的主要區別是:

  • 平臺搭配。PCLs的一個挑戰是,當你目標是多個平臺時,它仍然是一組特殊集合。對於 NuGet 包,可以確認的是,你必須列出庫文件名中的平臺。當新的平臺出現並支持相同的 APIs 時,這將導致問題。.NET 標準不存在這樣的問題,因爲你的目標版本不包含任何的平臺問題。
  • 平臺的可用性。目前 PCLs支持較爲寬泛的平臺,但是並不是所有的配置文件都具有相應的 .NET 標準版本。
  • 庫的可用性。PCLs的設計是爲了那些你無法依賴的、在選擇的平臺上無法運行的 APIs 和庫。因此,PCLs 項目將只允許引用其它的PCLs。.NET 標準是相似的,但它增加了對 .NET 框架的二進制文件的引用。因此,使用 .NET 2.0 的標準,你將有機會獲得更大的庫。

爲了做出明智的決定,我建議你:

  1. 使用APIs 端口來查看你的代碼庫,是如何與各種版本的.NET標準兼容的。
  2. 看.NET標準文檔,以確保你選用的平臺.NET標準是可用的。

例如,如果你想確認你是否能夠使用 .NET2.0 標準,你可以通過以下的 APIs 文件命令行工具並且像這樣運行你的庫類,來檢測應該使用 .NET1.6 標準還是 .NET2.0 標準:

> APIs port analyze -f C:\src\mylibs\ -t ".NET Standard,Version=1.6"^
                                      -t ".NET Standard,Version=2.0"

注: .NET 標準2.0 仍然在制定中,因此 APIs 的可用性隨時可能更改。我也建議你注意,那些在 .NET1.6 標準中可用,但是在 .NET2.0 標準中移除的APIs。

 

總結

我們已經創建了 .NET 標準,以便使得多個 .NET 平臺之間代碼的共享和複用變得更加容易。

在 .NET 2.0 標準中,我們更關注於兼容性。爲了在 .NET Core 和 UWP 中支持 .NET 2.0 標準,我們將擴展這些平臺,以便包括更多的現有的 APIs 。這也包含了兼容性功能,這種兼容性功能允許引用 .NET 框架中無法編譯的二進制文件。

展望未來,我們建議你使用 .NET 標準,而不是便攜式類庫。.NET 2.0 標準也會在即將到來的 Visual Studio “Dev 15”發佈的同時,進行推廣。你可以以一個 NuGet 包的形式,來引用 .NET 標準。對於 Visual Studio, VS Code 和 Xamarin Studio,將會有一流的庫類支持。

學習.NET的新標準,是爲了幫助我們更好地使用.NET進行項目開發。在開發時,也不忘藉助支持 .NET 的開發工具。如ComponentOneStudio Enterprise,這是一款專注於企業應用的 .NET 全功能控件套包,支持 WinForms、WPF、UWP、ASP.NET MVC 等多個平臺,幫助、在縮減成本的同時,提前交付豐富的桌面、Web和移動企業應用。

 

文章來源:by Immo Landwerth

 

原文鏈接:https://blogs.msdn.microsoft.com/dotnet/2016/09/26/introducing-net-standard/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章