.NET Standard 2.0 與 .NET 的未來與發展

大約 8/14 左右,官方正式 Announcing 了 ASP.NET Core 2.0,也同步的推出了 .NET Core 2.0、Entity Framework Core 2.0 也同時間推出了 Visual Studio 2017 的 15.3 版本,更同時也包含了 Visual Studio for MAC 等產品的釋出,哇!對!好大一包!這對開發人員來說真的是很大的驚喜。 

前言

就在 8/14 多項產品的釋出,這對於開發人員來說,無疑又是項新的開始,但是這些產品中,包括:Visual Studio 2017. ver. 15.3 與 Visual Studio for MAC 都表明了會支援 .net Standard 2.0 的開發,喔!對了,其實這一次所以釋出的亮點,我認為就是 .net Standard 2.0 了,為什麼這麼說呢?因為在所有 Announcing 的產品中,如:Entity Framework Core 2.0 、Visual Studio 2017 的 15.3 版本、以及 Visual Studio for MAC 等 都表明了此項推出為了支援 .net Standard 2.0,從這邊就可以看的出來,多項產品幾乎都為了 Support .net Standard 2.0 而 Release 的。

 

.NET Standard 2.0

此次 Release 的重要核心,就是 .net Standard 2.0 了,為什麼微軟近期會如此的重視 .net Standard 標準的統一,這就要從微軟一兩年前,以及後來 Build 2016 說起了,沒 Follow 到的朋友可參考文章最後的參考資料,簡單的從開發的角度來說,一個就是跨平台、另一個就是 Open Source 了,而 .NET Framework 若要跨平台,不能夠再像以往為了不同平台 OS 開發一套 .NET Framework,必須要有一套跨平台核心 Framework 也就是 .NET Core 了,但是即便有了 .NET Core ,現有開發的.net 套件也還是跨不過去,舉個例子:某 Third-Party 廠商所開發的 .net 套件如果是在 .NET Framework Full 4.6 完整版所編譯出來的 DLL 是沒有辦法在 .NET Core 當時的 1.0/1.1 的環境中被參考使用的,這類情形發生最多的就是我們開發人員最常用的 nuget packages 了,而這個問題,就算透過 PCLs 可攜式類別庫依然無法完全的解決,PCLs 雖然可以解決同一個 DLL 包含 Xamarin 與 UWP 的平台,但是到了 .NET Core 環境依然無法使用,而且 PCLs 如果 Support 越多,那麼 API 就更少的可憐,所以微軟發展了 .net Standard,如果還不了解 .net Standard 前期發展的朋友,可以參考筆者去年的文章 .NET 的未來與發展

 

再談 .NET Standard

這邊再補充一下官方對於 .net Standard 的一些解釋

  • .net Standard 是希望達到可共享的 API 程式庫,以便未來的 .net 程式庫有標準可以依循,並取代現有的可攜式類別庫 PCLs.
  • .net Standard 2.0 比先前的 1.6 支援的 1.6K 的 API 數更增加到了 32K 左右,大部分是有現有的 .NET Framework API 所移植過去的,透過這樣的方式讓現有 API 在未來的 .net Standard 中實現,包括外來期望會 Support UWP。
  • .net Standard 目前採相容模式,因為現有最大的 .NET 程式庫來源就是 NuGet Gallery 了,就算現在有 .net Standard 但是現有的 NuGet Packages 也不是所有的都能夠被使用,至少 .net Standard 2.0 也未支援到所有項目,舉個例子:某些已 WPF 為基礎而開發的 NuGet Packages 套件被安裝在不同平台之中,就算是 .net Standard 2.0 仍然會吐出 PlatformNotSupportedException 的錯誤訊息。
  • 目前 .net Standard 2.0 所 Support 的清單如下:
    • .NET Framework 4.6.1
    • .NET Core 2.0
    • Mono 5.4
    • Xamarin.iOS 10.14
    • Xamarin.Mac 3.8
    • Xamarin.Android 7.5
    • Upcoming version of UWP (expected to ship later this year)

詳細的實作支援可參考目前最新的 .NET Implmenetation Suppor

圖(一)、圖片取自:https://docs.microsoft.com/zh-tw/dotnet/standard/net-standard

 

如何建立 .net Standard 2.0 的類別庫?

我們先複習一下 .net Standard 當初的架構圖,當然事實上目前已經做到了。

圖(二)、.net Standard 架構圖,圖片取自:https://blogs.msdn.microsoft.com/dotnet/2016/09/26/introducing-net-standard/

當你安裝了 .net Core SDK 與 Visual Studio 2017 的 15.3 之後,您可以在新增專案的時候,在左邊的樹狀看見 .NET Standard

您可以在屬性視窗裡發現,預設的目標 Framework 即是 .net Standard 2.0 了

如何在 MAC 中 ASP.NET Core 2.0 環境中共享在 .NET 4.6.1 以 .net Standard 2.0 編譯出來的 DLLs?

接下來,筆者將做一個實驗,前面,我們提到了這個多,也就是 .net Standard 2.0 會相容且支援 .NET 4.6.1 ,因為微軟發現 .NET 4.6.1 目前最多人使用,從前面圖(一)的表格裡可以看的出來,從 .net Standard 2.0 開始,反而降回 4.6.1 ,不像先前的 .net Standard 1.6 的目標定為 4.6.2,從表格上也可以很清楚的看出,現在正是釋出的 .net Standard 2.0 不但可以與 .NET Core 2.0 相容,並可以同時使用在這一次同步釋出的 ASP.NET Core 2.0 之中。

所以,筆者來做一個簡單的測試,就是,筆者將上一步驟中,所建立的 .net Standard 2.0 的類別庫包裝成 NuGet 套件,並發佈到 NuGet Gallery 中,然後,在 MAC 環境中,我以 Visual Studio for MAC 來建立一個 ASP.NET Core 2.0 專案來測試引用這個 NuGet 套件,看看是否可以正確地被呼叫使用。

 

首先,分以下步驟進行:

一、撰寫 .net Standard 2.0 類別庫

由於只是為了測試,筆者撰寫一個非常簡單的類別庫 Utility,他只有一個類別,也只有一個方法,只做一件事情,就是取得本機的 HostName,這個熟悉 .NET 的應該都知道在 System.Net.Dns 裡就可以取得這個功能,程式碼如下,非常的簡單,對吧。

using System;

namespace Utility
{
	/// <summary>
	/// Utils.
	/// </summary>
	public class Utils
	{
		/// <summary>
		/// Gets the name of the host.
		/// </summary>
		/// <returns>The host name.</returns>
		public static string GetHostName()
		{
			return System.Net.Dns.GetHostName();
		}
	}
}

 

二、建立成 NuGet Packages

接著,就是將上一步驟中所編譯出來的 .net Standard 2.0 的 DLL 包裝成 NuGet Packages,這邊我們使用最簡單的方式,但是不要忘了下載最新的 NuGet Package Explorer (這部分 Click Once 安裝應該會自動搞定,除非你現在網路不通XD)

下方可以清楚的看見,新版的 NuGet Package Explorer 都同步的支援 .net Standard 2.0 的套件了!

套件名稱我就取名為「MyUtilityTest」,且為了測試,這個 MyUtilityTest 套件裡面,我只會提供一個 DLL 版本,也就是 net Standard 2.0。

這裡我在補充說明一下,為什麼我只加 .net Standard 2.0 而已?以前我們在開發 NuGet 元件供下載的時候,我們得同步的提供 net20, net30, net35, net40, net45, 甚至如果我還需要提供給 .NET Core 平台使用,我還得提供 netCore45,也就是我得在這個 NuGet 套件裡放置各種不同 Target Platform 的 DLL,非常的麻煩,雖然 NuGet Package Explorer 很貼心地都有支援。

舉個例子,著名的套件 Newtonsoft.Json 裡面就提供了各個 .NET 的目標平台外,也支援了 WP8, WAP8.1 等環境,如下圖:

 

三、發佈到 NuGet Gallery

前面動作完成後,接著舊式發佈到 NuGet Gallery 中了,下圖是我的 NuGet Gallery ,以及我們現在要測試的套件 MyUtilityTest

 

四、在 Windows 環境的 Visual Studio 2017 建立的 ASP.NET Core 2.0 專案中使用

接著,這個步驟中,我們要使用 Visual Studio 2017 來建立一個 ASP.NET Core 2.0 應用程式,並使用 ASP.NET Core 2.0 新增的 Razor Pages 來測試這個 MyUtilityTest 的 NuGet 套件。

首先,請將專案命名為 「WebPagesApplication1」,注意目標 .NET Framework 這邊需要用 4.6.1

然後請選擇 「空白」的應用程式

在專案裡新增一個資料夾 「Pages」,因為我們現在要用的是 ASP.NET Core 2.0 的新功能,叫做 「Razor Pages」,所以我們要在這個資料夾上點選滑鼠右鍵,並選擇「新增項目」

接著,將「Razor 頁面」加入,加入後你可以發現,在 「Index.cshtml」的底下,還有一個 「Index.cshtml.cs」,天阿,熟悉 ASP.NET Web Form 的朋友一定會說,這不就是 Code-Behind 嗎?看起來好熟悉對吧,但你可以這麼想,但.... 它跟 Code-Behind 骨子裡完全的大不相同阿!他所實作的仍然是與 MVC View Pages 相關的 ViewData/RediredToAction/ContentResult 等等與 MVC Controller 相關的屬性與方法。有興趣的朋友可以看一下 PageModel 的實作內容。

然後,是將剛剛發佈到 NuGet Gallery 上的 MyUtilityTest 套件加入到專案中

並撰寫 IndexModel 的 PageModel 的程式碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Utility;

namespace WebPagesApplication1.Pages
{
    public class IndexModel : PageModel
    {
        public string HostName { get; private set; }
        public void OnGet()
        {
            HostName = Utils.GetHostName();
        }
    }
}

程式碼非常的簡單,我們在新功能 PageModel 定義了一個屬性「HostName」,且必須是 public,那麼,我們就可以在 View 裡面的 Model 中使用的模型繫結中使用到這個 「模型」。

所以,我們只需要在「Index.cshtml」裡撰寫如下:

 

就可以再頁面上秀出本機的主機名稱。喔!另外不要忘了,空的 ASP.NET Core 2.0 預設在 Middleware 的 Configure 與 ConfigureServices 裡面還未加入對 MVC 這個 Middleware 的引用,請記得修改成如下:

那麼,這個 Razor Page 應該可以正常的執行,並秀出 Local 的主機名稱,如下:

 

五、同步在 Visual Studio for MAC 環境中建立相同專案方式測試

接下來,就是我在 MVC 環境中的 Visual Studio for MAC 建立相同的專案,參照相同的 .net Standard 2.0 為基準所編譯出來的 MyUtilityTest 的 NuGet 套件,並撰寫相同的程式碼,理論上,就官方的解釋,ASP.NET Core 2.0 完全相容以 .NET 4.6.1 為基礎所編譯出來的,並以 .net Standard 2.0 為標準的 DLL。所以,也就是說,我應該可以在完全不修改這個 NuGet 套件情況下,直接參考使用才對,底下我們就來測試看看。

首先,使用 Visual Studio for MAC 建立一個空的 ASP.NET Core 2.0 專案

接著,加入 MyUtilityTest 這個 NuGet 套件,Visual Studio for MAC 的操作方法是,在專案的「Dependency」的地方以滑鼠右鍵點選「Add Packages」

然後搜尋「MyUtilityTest」並安裝

由於 Visual Studio for MAC 已經做得非常簡易、且易於使用,在這邊的操作與 Visual Studio 2017 幾乎沒什麼不同,所以筆者在這裡就不再重複說明,主要差別在於,Visual Studio for MAC 不會自動再加入「Razor Page」時自動加入 PageModel 的程式碼檔案,這部分您可能要自行加入 class 檔案,並繼承 PageModel 類別。

還有,Visual Studio for MAC 可能不會自動加入 「MVC Import View Page」,您可能需要自行加入,並定義 Razor Page 的命名空間,否則你的 Razor Page 回沒有 IntelliSense 等相關功能。

由於,程式碼幾乎相同,您可以將 Visual Studio 2017 所撰寫的 PageModel 直接貼到 MAC 來用,因為同樣是 ASP.NET Core 環境,所以,我們就直接來看結果吧!

執行結果如下:

測試完後,發現非常的成功,可以順利的取用 .net Standard 2.0 的 NuGet 套件裡所提供的 GetHostName() 方法。

.NET 的未來與發展

這邊以 Web 開發角度來談,.NET 的跨平台仍然是主要發展內容,如果您是網頁程式開發人員,可以密切注意 ASP.NET Core 的發展趨勢,就目前 ASP.NET Core 2.0 來看有幾個特性:

  • 微軟一直想要降低學習門檻:微軟近期以來的動作不光是 IDE 工具更新迅速,對於開發人員的 FeedBack 幾乎也是有求必應,希望改善的不光是開發工具有更好的體驗、產能的提升,等等,更希望降低學習的門檻,並也擴大 .NET 的版圖到 Open Sources 領域。
  • 效能改善:從 .NET Core 推出到現在,我們所聽到的應該就是對於 Web Request 處理效能的提升,幾乎提升 15 ~ 20 倍以上,事實上真的是如此,全新的框架帶給開發者是一個全新的體驗。
  • 與微軟現有 Azure 的 Cloud 環境密切的整合:ASP.NET Core 從 ASP.NET 5 發展到現在,一直就與 Azure 有相當密切的整合,當然微軟因為工具之便能單鍵發布應用程式,不過也要 Azure 不斷的更新與支援才能辦到。光是 Azure 的進步已經不可同日而語了。
  • 微服務:由於輕量化的特性,使用 ASP.NET Core 執行在微服務中,如:Docker 或 Windows Container 中,微服務幾乎就是為了 ASP.NET Core 存在的,ASP.NET Core 本身的發布就已經不需要在像以前一樣需要安裝一整包的 .NET Framework 了,佈署輕量化特性讓他會於微服務的支援更是容易。
  • 真正的跨平台:小弟認為,NET Core 跨平台的目標,就像現有的 PHP、Perl、Python 一樣,未來你會在任一平台看見 .NET Core 的影子。
  • 持續增加:目前連 WCF 的跨到 .NET Core 之中了,我想未來只會越來越多,因為若跟現有 Full .NET Framework 相比,您應該會覺得 .NET Core 的 API 少的可憐,所以還有一段很長的路要走,但這也表示可發展的前途不可限量,未來只會一天筆意天完整,筆者聽到有些人以為 .NET Core 2.0 包含 Windows Form 的部分,事實上是沒有,但 WPF 未來跨到 .NET Core 平台的機會很高,因為先前 Silverlight 的子集事實上就已經可以跨平台了,而且體積縮得很小,筆者認為若是 Windows Form 機會不大,為什麼呢?因為 Windows Form 與 Win32 API/GDI 綁得太緊,我想不容拆出來,但 XMAL 與 WPF 部分 UI 我則認為是有機會的。這部分應該可以期待一下。

 

結語:

從以上例子不難看的出來,未來 .net Standard 會是統一所有平台的標準,雖然它現在還未支援 UWP,但官方表示即將支援,而且現在釋出的 .net Standard 2.0 的 API 數量幾乎是之前 1.6 的一倍,這表示可以期待下一版本的 .net Standard。如果您是元件的開發商,您開發的產品最好趁早支援 .net Standard,可免去未來還得為不同平台重複撰寫&編譯程式碼的麻煩。

 

參考資料:

https://blogs.msdn.microsoft.com/webdev/2017/08/14/announcing-asp-net-core-2-0/

https://www.microsoft.com/net/core#windowscmd

https://blogs.msdn.microsoft.com/dotnet/2017/08/15/the-week-in-net-net-core-2-0-asp-net-core-2-0-entity-framework-2-0-visual-studio-2017-update-3-enterprise-entity-framework-core-in-boston-and-links/

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

https://channel9.msdn.com/Blogs/dotnet/NET-Core-20-Released?ocid=player

https://github.com/Microsoft/dotnet/blob/master/releases/README.md

https://github.com/dotnet/standard/blob/master/docs/versions/netstandard2.0.md

https://docs.microsoft.com/zh-tw/dotnet/standard/net-standard

 


 

簽名:

學習是一趟奇妙的旅程

這當中,有辛苦、有心酸、也有成果。有時也會有瓶頸。要能夠繼續勇往直前就必須保有一顆最熱誠的心。

軟體開發之路(FB 社團)https://www.facebook.com/groups/361804473860062/

Gelis 程式設計訓練營(粉絲團)https://www.facebook.com/gelis.dev.learning/


 

如果文章對您有用,幫我點一下讚,或是點一下『我要推薦,這會讓我更有動力的為各位讀者撰寫下一篇文章。

非常謝謝各位的支持與愛護,小弟在此位各位說聲謝謝!!! ^_^