.NET Standard - 揭祕 .NET Core 和 .NET Standard[轉自MSDN]

做爲 .NET 系列的最新成員,.NET Core 和 .NET Standard 的概念及其與 .NET Framework 的區別並不十分明確。在本文中,我將準確介紹每一個產品及其適用場景。 web

在詳細介紹以前,建議先審視一下 .NET 的整體狀況,瞭解 .NET Core 和 .NET Standard 是如何在這一體系中發揮做用的。.NET Framework 是在 15 年前首次推出(我怎麼記得2008年時我就在用.net framework1.1了?),當時只有一個 .NET 堆棧可用於生成 Windows 桌面和 Web 應用程序。從那之後,出現了其餘 .NET 實現。例如,可用於生成 iOS/Android 移動應用和 macOS 桌面應用程序的 Xamarin,如圖 1 所示。 後端

1.NET 整體狀況 瀏覽器

下面說明了 .NET Core 和 .NET Standard 是如何在這一體系中發揮做用的: 服務器

  • .NET Core:這是最新的 .NET 實現。它不只開放源代碼,並且還適用於多個 OS。使用 .NET Core,能夠生成跨平臺的控制檯應用程序、ASP.NET Core Web 應用程序和雲服務。
  • .NET Standard:這是全部 .NET 實現都必須實現的一組基本 API,一般稱爲"基類庫 (BCL)"。經過定目標到 .NET Standard,能夠生成能跨全部 .NET 應用程序共享的庫,不管它們是在哪一個 .NET 實現或 OS 上運行。

.NET Core 簡介 網絡

做爲 .NET Framework 和 Silverlight 分支,.NET Core 是全新的 .NET 實現,不只跨平臺,並且還徹底開放源代碼。經過啓用獨立式 XCOPY 部署,它已通過優化,更適用於移動和服務器工做負載。 app

爲了可以更好地認識 .NET Core,接下來將深刻了解如何進行 .NET Core 開發。爲此,將同時探索新的命令行工具。也可使用 Visual Studio 2017 進行 .NET Core 開發,但本文讀者極可能已至關熟悉 Visual Studio,所以我將重點介紹新體驗。 框架

在 .NET 建立之初,它通過了大量優化,以便用戶可以在 Windows 上快速開發應用程序。實際上,這意味着 .NET 開發與 Visual Studio 是不可分開的。能夠確定的是:使用 Visual Studio 進行開發是一種奇妙的感覺。這樣開發的工做效率超高,調試程序是我使用過的最好用的。 async

不過,有時,使用 Visual Studio 並非最便捷的選擇。假設只是想經過 .NET 學習 C#。在這種狀況下,就無需下載並安裝好幾個 GB 的 IDE。或者,假設要經過 SSH 訪問 Linux 計算機。在這種狀況下,使用 IDE 根本就行不通。又或者,假設只是喜歡使用命令行接口 (CLI)。 工具

正由於此,名爲 .NET Core CLI 的一流 CLI 誕生了。.NET Core CLI 的主驅動程序稱爲"dotnet"。 它可用於開發的幾乎全部方面,包括建立、生成、測試和打包項目。接下來,將瞭解具體操做。 學習

首先,建立並運行 Hello World 控制檯應用程序(我使用的是 Windows PowerShell,而在 macOS 或 Linux 上使用 Bash 也一樣有效):(命令行下建立項目、編譯,對我這樣的老年選手來除了裝逼應該沒什麼別的用處了,固然我也沒心思記住它們)

$ dotnet new console -o hello

$ cd hello

$ dotnet run

Hello World!

CLI 中的"dotnet new"命令至關於 Visual Studio 中的"文件 | 新建項目"。能夠建立各類不一樣類型的項目。鍵入"dotnet new"能夠查看預安裝的各類模板。

如今,將一些邏輯提取到類庫中。爲此,請先建立與"hello"項目平行的類庫項目:

$ cd ..

$ dotnet new library -o logic

$ cd logic

因爲要封裝的邏輯是構造 Hello World 消息,所以將 Class1.cs 的內容更改成如下代碼:

namespace logic

{

publicstaticclass HelloWorld

{

publicstaticstring GetMessage(string name) => $"Hello {name}!";

}

}

此時,還應將 Class1.cs 重命名爲 HelloWorld.cs:

$ mv Class1.cs HelloWorld.cs

請注意,無需由於有此更改而更新項目文件。.NET Core 中使用的新項目文件只包括項目目錄中的全部源文件。所以,添加、刪除和重命名文件再也不須要修改項目。這樣一來,能夠更順暢地使用命令行執行文件操做。

若要使用 Hello World 類,須要將 hello 應用程序更新爲引用邏輯庫。爲此,能夠編輯項目文件,也可使用 dotnet add reference 命令:

$ cd ../hello

$ dotnet add reference ../logic/logic.csproj

如今,將 Program.cs 文件更新爲使用 HelloWorld 類,如圖 2 所示。

圖 2:將 Program.cs 文件更新爲使用 HelloWorld 類

using System;

using logic;

namespace hello

{

class Program

{

staticvoid Main(string[] args)

{

Console.Write("What's your name: ");

var name = Console.ReadLine();

var message = HelloWorld.GetMessage(name);

Console.WriteLine(message);

}

}

}

若要生成並運行應用程序,只需鍵入 dotnet run:

$ dotnet run

What's your name: Immo

Hello Immo!

還能夠經過命令行建立測試。CLI 支持 MSTest 和經常使用的 xUnit 框架。此示例使用 xUnit:

$ cd ..

$ dotnet new xunit -o tests

$ cd tests

$ dotnet add reference ../logic/logic.csproj

更改 UnitTest1.cs 內容以添加測試,如圖 3 所示。

圖 3:更改 UnitTest1.cs 內容以添加測試

using System;

using Xunit;

using logic;

namespace tests

{

publicclass UnitTest1

{

[Fact]

publicvoid Test1()

{

var expectedMessage = "Hello Immo!";

var actualMessage = HelloWorld.GetMessage("Immo");

Assert.Equal(expectedMessage, actualMessage);

}

}

}

如今,能夠調用 dotnet test 運行測試:

$ dotnet test

Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.

Test Run Successful.

爲了讓操做變得更有趣一點,將建立簡單的 ASP.NET Core 網站:

$ cd ..

$ dotnet new web -o web

$ cd web

$ dotnet add reference ../logic/logic.csproj

編輯 Startup.cs 文件,並將 app.Run 調用更改成使用 HelloWorld 類,以下所示:

app.Run(async (context) =>

{

var name = Environment.UserName;

var message = logic.HelloWorld.GetMessage(name);

await context.Response.WriteAsync(message);

});

若要啓動開發 Web 服務器,只需再次運行 dotnet run:

$ dotnet run

Hosting environment: Production

Now listening on: http://localhost:5000

Application started. Press Ctrl+C to shut down.

轉到所顯示的 URL(應爲 http://localhost:5000)。

此時,項目結構應如圖 4 所示。

圖 4:建立的項目結構

$ tree /f

├───hello

│ hello.csproj

│ Program.cs

├───logic

│ HelloWorld.cs

│ logic.csproj

├───tests

│ tests.csproj

│ UnitTest1.cs

└───web

Program.cs

Startup.cs

web.csproj

爲了可以更方便地使用 Visual Studio 編輯文件,還將建立解決方案文件,並將全部項目添加到解決方案中:

$ cd ..

$ dotnet new sln -n HelloWorld

$ ls -fi *.csproj -rec | % { dotnet sln add $_.FullName }

能夠看到,.NET Core CLI 功能很是強大,可以爲具備其餘背景的開發者提供至關熟悉的精益體驗。雖然此過程是將 dotnet 與 Windows PowerShell 結合使用,但若是是在 Linux 或 macOS 上,使用體驗也會很是類似。

.NET Core 的另外一巨大優點在於,它支持獨立式部署。可使用 Docker 對應用程序進行容器化處理,以便它可以有本身的 .NET Core 運行時副本。這樣一來,能夠在使用不一樣版本 .NET Core 的同一臺計算機上運行各類應用程序,而它們則互不干擾。因爲 .NET Core 開放源代碼,所以還能夠添加每日版或甚至本身修改或生成的版本,其中可能包括本身所作的修改。不過,這並不在本文的討論範圍以內。

.NET Standard 簡介

在開發者生成新式體驗時,應用程序一般跨越多種外形規格,於是也就跨越多個 .NET 實現。今時今日,客戶很是但願能夠在手機上使用 Web 應用程序,並但願可以經過基於雲的後端共享數據。使用筆記本電腦時,他們也但願能夠經過網站得到訪問權限。對於本身的基礎結構,極可能但願能夠藉助命令行工具和潛在的桌面應用程序,容許員工管理系統。請參閱圖 5,瞭解具備此類用途的不一樣 .NET 實現。

5:介紹了 .NET 實現

  

OS

開源

用途

.NET Framework

Windows

N

用於生成在 IIS 上運行的 Windows 桌面應用程序和 ASP.NET Web 應用程序。

.NET Core

WindowsLinuxmacOS

Y

用於生成跨平臺的控制檯應用程序、ASP.NET Core Web 應用程序和雲服務。

Xamarin

iOSAndroidmacOS

Y

用於生成適用於 iOS Android 的移動應用,以及適用於 macOS 的桌面應用程序。

.NET Standard

Y

用於生成能夠從全部 .NET 實現(如 .NET Framework.NET Core Xamarin)引用的庫。


在這樣的環境下,代碼共享成爲重大挑戰。須要瞭解 API 的可用位置,並確保共享組件僅使用跨全部要用 .NET 實現都支持的 API。

此時,.NET Standard 就派上用場了。.Net Standard 是一種規範。每一個 .NET Standard 版本都定義了一組 API。爲了與相應版本保持一致,全部 .NET 實現都必須提供這些 API。能夠將 .NET Standard 看做是另外一個 .NET 堆棧,不一樣之處在於沒法爲其生成應用程序,只能生成庫。若但願能夠從任意位置引用庫,應對庫使用此 .NET 實現。

你們不由想知道,.NET Standard 涵蓋了哪些 API。若是熟悉 .NET Framework,就應該熟悉我以前提到的 BCL。BCL 是與 UI 框架和應用程序模型無關的一組基礎 API。它包括基元類型、文件 I/O、網絡、反射、序列化、XML 等。

全部 .NET 堆棧都會實現某版 .NET Standard。經驗法則是,生成新版 .NET 實現時,一般都會實現最新版 .NET Standard。

很貼切的例子是 HTML 和瀏覽器:將 HTML 規範看做是 .NET Standard,將不一樣的瀏覽器看做是 .NET 實現,如 .NET Framework、.NET Core 和 Xamarin。

此時,你們可能很是好奇,如何使用 .NET Standard。實際上,你們已經知道了。還記得以前建立邏輯類庫時的情形嗎? 接下來,將深刻了解一下項目文件:

$ cd logic

$ cat logic.csproj

<Project Sdk="Microsoft.NET.Sdk">

 

<PropertyGroup>

<TargetFramework>netstandard2.0</TargetFramework>

</PropertyGroup>

 

</Project>

將此文件與"hello"控制檯應用程序項目文件進行對比:

$ cd ..\hello

$ cat hello.csproj

<Project Sdk="Microsoft.NET.Sdk">

 

<ItemGroup>

<ProjectReference Include="..\logic\logic.csproj" />

</ItemGroup>

 

<PropertyGroup>

<OutputType>Exe</OutputType>

<TargetFramework>netcoreapp2.0</TargetFramework>

</PropertyGroup>

 

</Project>

能夠看到,邏輯庫的 TargetFramework 值爲 netstandard2.0,而控制檯應用程序的值爲 netcoreapp2.0。TargetFramework 屬性指明要定目標到的 .NET 實現。所以,控制檯應用程序定目標到 .NET Core 2.0,而庫定目標到 .NET Standard 2.0。也就是說,不只能夠從 .NET Core 應用程序引用邏輯庫,還能夠從生成的 .NET Framework 或 Xamarin 應用程序引用邏輯庫。

遺憾的是,目前可用的大多數庫都還沒有定目標到 .NET Standard。大多數庫都定目標到 .NET Framework。固然,並非全部庫均可以(或甚至應該)定目標到 .NET Standard。例如,包含 Windows Presentation Foundation (WPF) 控件的庫須要定目標到 .NET Framework,由於 UI 並非標準的一部分。不過,許多常規用途庫定目標到 .NET Framework 只是由於,在它們建立時尚未 .NET Standard。

在 .NET Standard 2.0 推出後,API 集變得很是大,大多數(若是不是所有的話)常規用途庫能夠定目標到 .NET Standard。所以,目前 NuGet 上的所有庫中有 70% 只使用如今屬於 .NET Standard 的 API。儘管如此,其中只有一小部分明確標註爲與 .NET Standard 兼容。

爲了讓開發者無障礙地使用它們,添加了一種兼容性模式。若是安裝的 NuGet 包沒有爲目標框架提供庫,也沒有爲 .NET Standard 提供庫,那麼 NuGet 會轉而求助於 .NET Framework。也就是說,能夠引用 .NET Framework 庫,就像是定目標到 .NET Standard 同樣。

我將演示一下具體操做。在此示例中,我將使用名爲 PowerCollections 的經常使用集合庫,它是在 2007 年編寫的。它有一段時間沒有更新了,仍定目標到 .NET Framework 2.0。我將從 NuGet 將此庫安裝到 hello 應用程序中:

$ dotnet add package Huitian.PowerCollections

此庫提供了 BCL 沒有的其餘集合類型,如不保證排序的包。接下來,將把 hello 應用程序更改成使用此庫,如圖 6 所示。

圖 6:使用 PowerCollections 的示例應用程序

using System;

using Wintellect.PowerCollections;

namespace hello

{

class Program

{

staticvoid Main(string[] args)

{

var data = new Bag<int>() { 1, 2, 3 };

foreach (var element in data)

Console.WriteLine(element);

}

}

}

若是運行程序,將會看到如下警告:

$ dotnet run

hello.csproj : warning NU1701: Package 'Huitian.PowerCollections 1.0.0' was restored using'.NETFramework,Version=v4.6.1' instead of the project target framework '.NETCoreApp,Version=v2.0'. This may cause compatibility problems.

1

3

2

那麼,究竟發生了什麼? hello 應用程序定目標到 .NET Core 2.0。因爲 .NET Core 2.0 實現的是 .NET Standard 2.0,所以還有可引用 .NET Framework 庫的兼容性模式。不過,並非全部 .NET Framework 庫都適用於各類 .NET 實現。例如,它們可能會使用 Windows 窗體或 WPF API。因爲沒法肯定具體狀況,所以 NuGet 會顯示警告消息,提醒注意這種狀況,這樣就不會浪費時間排查可能由此致使的問題了。

請注意,每次生成時都會看到此警告。這樣可避免在包安裝期間根本看不到警告或忘記這種狀況的問題。

固然,沒有什麼比每次生成時都須要忽略沒法做爲行動依據的警告更糟糕的了。所以,建議在驗證應用程序後,爲相應包禁用警告。因爲應用程序運行正常(正確輸出了所建立的包的內容),所以如今能夠取消警告。爲此,請編輯 hello.csproj 文件,並將 NoWarn 屬性添加到包引用中:

<PackageReference Include="Huitian.PowerCollections" Version="1.0.0"

NoWarn="NU1701" />

若是如今從新運行應用程序,就不再會看到警告了。若是安裝另外一個使用兼容性模式的包,也會看到能夠取消的相應包警告。

使用新工具,還可讓類庫項目建立屬於生成的 NuGet 包。這樣一來,能夠更輕鬆地與全世界共享庫(經過推送到 nuget.org),也能夠僅在組織內共享(經過推送到你們在 Visual Studio Team Services 或 MyGet 上本身的包源)。新項目還支持多重定目標,這樣就能夠生成一個適用於多個 .NET 實現的項目。也就是說,可使用條件編譯 (#if) 來調整庫,使其適應特定的 .NET 實現。還能夠生成平臺專屬 API 的 .NET Standard 包裝器。不過,這些都不在本文的討論範圍以內。

結束語

.NET Standard 是全部 .NET 實現都必須提供的 API 規範。這樣一來,可讓 .NET 系列保持一致,並生成可以從任何 .NET 實現引用的庫。它取代了生成共享組件的 PCL。

.NET Core 是更適合使用 ASP.NET Core 生成控制檯應用程序、Web 應用程序和雲服務的 .NET Standard 實現。它的 SDK 隨附功能很是強大的工具,除了支持 Visual Studio 開發外,還支持基於命令行的完整開發工做流。

相關文章
相關標籤/搜索