2017 年 9 月

第 32 卷,第 9 期

本文章是由機器翻譯。

.NET Standard - 揭開 .NET Core 與 .NET Standard 的神秘面紗

Immo Landwerth | 2017 年 9 月

做為最新的成員.NET 系列產品中,沒有太多.NET Core 和.NET 標準和它們的差異會從.NET Framework 而混淆。本文將說明完全哪些每一種是並查看何時應該選擇每一個。

前先詳細資料,最好先查看.NET 以查看.NET Core 和.NET 標準適用於什麼情況的較大的圖片。When.NET Framework 首次推出 15 年前,它有單一的.NET 堆疊,您可以使用建置的 Windows 桌面和 Web 應用程式。從那時起,其他.NET 實作應有,例如: Xamarin,您可用來建置 iOS、 Android 與非 macOS 桌面應用程式的行動應用程式中所示圖 1

.NET 環境

圖 1 的.NET 環境

以下是如何.NET Core 和.NET 標準納入此:

  • .NET core:這是最新的.NET 實作。它是開放原始碼並可供多個作業系統。.NET core,您可以建置跨平台的主控台應用程式和 ASP.NET Core Web 應用程式和雲端服務。
  • .NET 標準:這是基本 (通常稱為基底類別程式庫或 BCL) 的 Api 集,都必須實作所有的.NET 實作。目標為.NET 標準,您可以建立程式庫,您可以在中共用您的.NET 應用程式,不論它們執行的.NET 實作或作業系統上。

.NET Core 簡介

.NET core 是新跨平台,並完全開啟原始碼.NET 實作已分叉,從.NET Framework 和 Silverlight。它被適合行動和伺服器工作負載,藉由啟用獨立的 XCOPY 部署。

若要取得更佳的感覺.NET Core,讓我們進一步查看哪些開發適用於.NET Core 看起來。讓我們來執行這項操作時瀏覽新的命令列工具。您也可以使用 Visual Studio 2017 為.NET Core 開發工作,但因為您正在閱讀本文,機會我將焦點放在新的體驗,讓您很熟悉,Visual Studio。

建立.NET 後,它已徹底最佳化 Windows 上快速的應用程式開發。在實務上,這表示,.NET 開發與 Visual Studio 中密不可分的朋友。並確定件事:使用 Visual Studio 進行開發。 火Super 生產力,偵錯工具是關閉我使用過的最佳的指針。

不過,有一些情況下,使用 Visual Studio 仍未的最方便的選項。例如,假設您想要了解 C#.net 只播放:您不應該必須下載並安裝數 gb IDE。或者,假設您透過 SSH 存取 Linux 機器使用的 IDE 不只是可行的。或者,假設您是只要偏好使用命令列介面 (CLI) 的人。

這就是為什麼第一級的 CLI 已建立,請呼叫.NET Core CLI。.NET Core CLI 主要驅動程式叫做 「 dotnet。 」 您可以將它用於開發程式時,包括建立、 建置、 測試及封裝專案的幾乎所有層面。我們來看看這好像。

開始建立及執行 Hello World 主控台應用程式 (使用 PowerShell 在 Windows 中,但這運作地一樣良好的 Bash macOS 或 Linux 上):

$ dotnet new console -o hello
$ cd hello
$ dotnet run
Hello World!

「 新 dotnet"命令相當於 CLI 的檔案 |在 Visual Studio 中的新專案。您可以建立各種不同的專案類型。輸入 「 新 dotnet 「 若要查看不同已預先安裝的範本。

現在,我們將某些邏輯解壓縮到 [類別庫。若要這樣做,請先建立類別庫專案平行 hello 專案:

$ cd ..
$ dotnet new library -o logic
$ cd logic

您想要將封裝的邏輯的 Hello World 訊息建構,因此將 Class1.cs 的內容變更為下列程式碼:

namespace logic
{
  public static class HelloWorld
  {
      public static string GetMessage(string name) => $"Hello {name}!";
  }
}

此時,您應該也將 Class1.cs 重新命名為 HelloWorld.cs 至:

$ mv Class1.cs HelloWorld.cs

請注意,您不必更新這項變更的專案檔。.NET Core 中使用新的專案檔案只需要包含所有原始程式檔,從專案的目錄。因此,在加入、 移除和重新命名檔案並不需要再修改專案。這可讓檔案作業從命令列更順暢。

若要使用 HelloWorld 類別,您需要更新 hello 應用程式參考的邏輯程式庫。您可以藉由編輯專案檔執行這項操作,或使用 dotnet 新增參考] 命令:

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

現在,更新 Program.cs 檔案,以使用 HelloWorld 類別,如中所示圖 2

圖 2 更新 Program.cs 檔案中使用 HelloWorld 類別

using System;
using logic;
namespace hello
{
class Program
{
static void Main(string[] args)
{
Console.Write("What's your name: ");
var name = Console.ReadLine();
var message = HelloWorld.GetMessage(name);
Console.WriteLine(message);
}
}
}

若要建置並執行您的應用程式,只要輸入 dotnet 執行:

$ 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
{
public class UnitTest1
{
[Fact]
public void Test1()
{
var expectedMessage = "Hello Immo!";
var actualMessage = HelloWorld.GetMessage("Immo");
Assert.Equal(expectedMessage, actualMessage);
}
}
}

現在,您可以藉由叫用 dotnet 測試執行測試:

$ dotnet test
Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.
Test Run Successful.

若要讓事情更有可看性,讓我們來建立簡單的 ASP.NET Core Web 網站:

$ cd ..
$ dotnet new web -o web
$ cd web
$ dotnet add reference ../logic/logic.csproj

編輯 Startup.cs 檔案並將應用程式的引動過程。執行使用 HelloWorld 類別,如下所示:

app.Run(async (context) =>
{
  var name = Environment.UserName;
  var message = logic.HelloWorld.GetMessage(name);
  await context.Response.WriteAsync(message);
});

若要啟動開發 Web 伺服器,只要使用 dotnet 重新執行:

$ 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 的另一項大優點是它支援獨立的部署。您無法化您的應用程式的方式,它有本身的.NET 核心執行階段使用 Docker。這可讓您使用不同的.NET Core 版本,但它們不在相同電腦上執行不同的應用程式互相干擾。因為.NET Core 開放原始碼,您也可以包含夜間組建或甚至版本您已修改或建立您自己,有可能包含您所做的修改。不過,這超出本文的範圍。

.NET 標準簡介

當您建置現代化的經驗時,請您的應用程式經常會跨越多個表單係數,因此,多個.NET 實作。在這一天和 age,客戶幾乎預期它們可讓您的 Web 應用程式從其行動電話,您可以透過以雲端為基礎的後端中共用資料。使用膝上型電腦,他們也想要透過網站的存取。和您自己的基礎結構,您可能想要使用命令列工具,並可能甚至可讓您管理系統的人員的桌面應用程式。請參閱圖 5針對不同的.NET 實作到這個的播放方式。

圖 5.NET 實作 (implementation) 的描述

  作業系統 開放原始碼 用途
.NET Framework Windows 不可 用來建立 Windows 傳統型應用程式和 ASP.NET Web 應用程式在 IIS 上執行。
.NET Core Windows、 Linux、 macOS 希望 用來建置跨平台的主控台應用程式和 ASP.NET Core Web 應用程式和雲端服務。
Xamarin iOS、 Android、 macOS 希望 用來建立適用於 iOS 和 Android 的行動應用程式以及 macOS 的桌面應用程式。
.NET 標準 不適用 希望 用來建立程式庫,您可以從所有的.NET 實作,例如.NET Framework 中,.NET Core 和 Xamarin 參考。

在這類環境中,程式碼共用會成為主要的挑戰。您需要了解有可用的 Api,以確保共用的元件,只能使用對您所使用的所有.NET 實作所能使用的 Api。

而這就是指.NET 標準來源。。NET 標準是一種規格。每個標準的.NET 版本定義的所有.NET 實作必須以符合該版本都提供的 Api。您可以將它視為尚未-其他.NET 堆疊,不同之處在於您無法為它唯一的程式庫來建置應用程式。您應該使用的程式庫,您想要從每個地方參考.NET 實作它。

您可能會猜想其中涵蓋應用程式開發介面.NET 標準。如果您熟悉.NET Framework,則您應該熟悉 BCL,先前所述。BCL 是基本的 UI 架構和應用程式模型應用程式開發介面的集合。它包含基本型別、 檔案 I/O、 網路功能、 反映、 序列化、 XML 和更多。

所有的.NET 堆疊實作某些版本的.NET 標準。根據經驗法則是當產生.NET 實作的新版本,它將通常實作的標準.NET 最新可用版本。

很好的類比是 HTML 和瀏覽器:將 HTML 規格做為標準.NET 和.NET 實作,例如.NET Framework 中,.NET Core 和 Xamarin 為不同的瀏覽器。

此時,您可能知道如何,您可以使用標準.NET。事實上,您已經有。請記住,當我們稍早建立的邏輯類別程式庫? 讓我們看看專案檔:

$ 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 標準 2.0 為目標。這表示您可以參考邏輯的程式庫,而不只是從.NET Core 應用程式中,從.NET Framework 或 Xamarin 所建置的應用程式。

不幸的,大部分可用程式庫目前不目標.NET 標準,尚未。其中大部分的目標.NET Framework。當然,並非所有的程式庫可以 (或甚至應該) 的目標.NET 標準。比方說,程式庫,其中包含 Windows Presentation Foundation (WPF) 控制項為目標.NET Framework 的需求,因為 UI 不是標準的一部分。不過,許多一般用途的文件庫只為目標.NET Framework 因為.NET 標準只要不存在時,他們所建立。

.NET Standard 2.0 中,使用 API 集是夠大,因此大部分,如果不是所有的一般用途的程式庫可鎖定目標.NET 標準。如此一來,70%的 NuGet 存在的所有程式庫目前只使用現在已納入.NET 標準的 Api。儘管如此,只有一小部份它們被明確標示為要與標準.NET 相容。

若要解除封鎖使用這些開發人員,已新增相容性模式。如果您安裝並未提供您的目標 framework 的程式庫,也不會提供一個標準.NET NuGet 套件,NuGet 會嘗試改為使用.NET Framework。換句話說,您可以參考.NET Framework 程式庫,其目標.NET 標準。

我將示範這好像。在範例中,我將會使用稱為 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
{
static void 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 標準 2.0 時,它也有參考.NET Framework 程式庫的相容性模式。不過,並非所有的.NET Framework 程式庫會處理所有的.NET 實作。例如,他們可能會使用 Windows Form 或 WPF 應用程式開發介面。NuGet 有無從得知,因此它可讓您一則警告訊息讓您知道此情況並不會浪費時間可能是因為這樣的問題進行疑難排解。

請注意,您會取得每次建置此警告。這可避免此問題,您只是看不封裝在安裝期間,警告或忘記其相關。

當然,沒有比您要忽略每次建置的 unactionable 警告。因此,這裡的概念是,驗證您的應用程式之後,您可以再停用該封裝的警告。應用程式執行順利 (它正確列印您所建立的屬性包的內容),因為您現在可以隱藏警告。若要這樣做,請編輯 hello.csproj 檔案並將 /nowarn 屬性加入至封裝參考:

<PackageReference Include="Huitian.PowerCollections" Version="1.0.0" 
  NoWarn="NU1701" />

如果您現在再次執行應用程式,則應該消失警告。您應該安裝使用的相容性模式的另一個封裝,您會收到警告,您可以隱藏時,以及該套件。

新的工具也可讓類別庫專案組建的一部分產生 NuGet 封裝。這可讓您更容易與 world (藉由推送到 nuget.org) 或只是組織內的程式庫共用 (藉由推送到您自己的封裝在 Visual Studio Team Services 或 MyGet 摘要)。新的專案也支援多目標功能,可讓您建立多個.NET 實作的單一專案。這表示您可以使用條件式編譯 (#if) 來調整特定的.NET 實作的程式庫。它也可讓您建置平台專屬的 Api 的.NET 標準包裝函式。不過,所有作業,已超出本文的範圍。

結論

.NET 標準是一種規格的所有.NET 實作必須都提供的 Api。它.NET 家族保持一致,並可讓您建置程式庫,您可以使用任何.NET 實作。它會取代 PCLs 建置共用的元件。

.NET core 是.NET 標準最佳化建置主控台應用程式、 Web 應用程式和使用 ASP.NET Core 的雲端服務的實作。其 SDK 隨附功能強大的工具,Visual Studio 開發除了支援完整的命令列開發工作流程。您可以進一步了解他們在 aka.ms/netstandardfaqaka.ms/netcore


Immo Landwerth 是 Microsoft 的.NET 上運作的程式經理。他著重於.NET 標準、 BCL 和應用程式開發介面的設計。


MSDN Magazine 論壇中的這篇文章的討論