【重榜?】.NET 6 Preview 1 開箱上手!帶你嘗試新版本更新!

痴者工良發表於2021-02-19


最近 .NET 6 Preview 1 釋出了,.NET 統一是此版本的核心。大家可以讀一下原文部落格:

https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-1/

.NET 6.0 SDK 和 Runtime 下載地址:

https://dotnet.microsoft.com/download/dotnet/6.0

下面筆者將給大家介紹一下 .NET 6 Preview 1 目前的更新內容和上手嘗試一些好玩的更新。

本文並非翻譯文章,純手工打造。

跨平臺 UI 應用

.NET6 對多平臺(Android、IOS等)介面應用程式做了統一,提供了在多種平臺和社保上一致的體驗,並且可以在移動應用和 PC桌面程式之間共享更多的程式碼。多平臺統一工具包是基於 Xamarin.Forms 的整合和擴充,使得我們可以開發 Windows、MacOS、Android 和 IOS 桌面應用。

目前 Visual Studio 支援 Windows 和 MacOS,在已經安裝了 .NET6 SDK 的機器上,釋出的桌面程式可以在 Windows 和 MacOS 上執行,如果要支援 Android 和 IOS ,則需要下載另外兩個包。這是因為 Windows 和 MacOS 可以通過安裝 .NET6 Runtime 去執行程式,執行的是 .dll 檔案(IL中間程式碼),而 Android 和 IOS 都是釋出和執行本機程式碼。

# Windows 下載
Microsoft.NET.Workload.Android.11.0.200.85.msi
Microsoft.NET.Workload.iOS.14.3.100-ci.main.1079.msi

# MacOS 下載
Microsoft.NET.Workload.Android-11.0.200-ci.master.85.pkg
Microsoft.iOS.Bundle.14.3.100-ci.main.1079.pkg

讀者可以到 https://github.com/dotnet/net6-mobile-samples 查詢下載連結,發現不開代理下載不了,各位請注意。

建立Xamarin專案

.NET6 執行時有 android 和 ios 的特殊標記,要支援移動應用,需要指定名稱,如要支援 Android,在 .csproj 檔案中:

    <TargetFramework>net6.0-android</TargetFramework>

下面是一個 Xamarin.Forms 應用的 .csproj 模板:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net6.0-android;net6.0-ios</TargetFrameworks>
    <RuntimeIdentifier>ios-x64</RuntimeIdentifier>
    <OutputType>Exe</OutputType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Xamarin.Forms" Version="4.8.0.1364" GeneratePathProperty="true" />
  </ItemGroup>
</Project>

當然,要釋出或者除錯程式,需要 SDK 或 模擬器,例如安卓需要 Android SDK以及Android SDK Platform 30,釋出的時候也需要指定:

dotnet build HelloForms -t:Run -f net6.0-android
dotnet build HelloForms -t:Run -f net6.0-ios

官方的示例專案中,nuget 包需要訪問 pkgs.dev.azure.com,不代理訪問不了。因此,這個示例專案搞不了,大家看著過過癮就行。

目前 .NET6 Targeting 有:

  • net6.0
  • net6.0-android
  • net6.0-ios
  • net6.0-maccatalyst
  • net6.0-macos
  • net6.0-tvos
  • net6.0-windows

Blazor 桌面應用

我想,看到這個更新,最開心的是 Ant Design of Blazor 專案的主導作者 James Yeung 吧。

img

james_mvp

.NET6 中,可以將 Blazor 擴充混合到 UI 應用程式中,將 Web 和本機 UI 結合在一起,可以在桌面中嵌入執行。Blazor 混合開發的方式,稱為 Blazor Hybrid Apps。

.NET Core 3.0 支援 Blazor Server,3.1 支援 Blazor WebAssembly,Blazor WebAssembly 使用 Mono 執行時,很多 .NETer 應該體驗過 Blazor 開發,WebAssembly 目前來看還是太大了(.NET Core 3.x),還有效能差等問題。後續 .NET 版本對其進行了大量優化。

VS2019 Preview4 中這個模板名稱變成了 Blazor WebAssembly App ,實際上就是 WebAssembly,加上了 App 這個名稱,但是並不代表是 UI 程式,它依然是 web。

BlazorWebAssemblyApp

迴歸正題,.NET6 更新的部落格說這個 Blazor 可以跟 MAUI一起搞,但是部落格並沒有提到 Demo 和實現細節,可能還在繼續開發中,Preview 1 可能暫時看不了。那 TM 我下載 VS2019 Preview4 後,還是不能直接建立???耍我呢?怎麼體驗這個 Blazor 開發桌面應用?

不久前有人建立了這個 Issue:https://github.com/Webreaper/Damselfly/issues/108

不過,Blazor 倒是可以跟移動應用搞一起,有個專案叫 Mobile Blazor Bindings,可以將 Blazor 結合到 Xamarin 中,這個專案在 .NET Core 3.x 就已經支援了。

專案地址:https://github.com/dotnet/MobileBlazorBindings

示例程式碼:

<StackLayout>
    <Label FontSize="30">You pressed @count times </Label>
    <Button Text="+1" OnClick="@HandleClick" />
</StackLayout>

@code {
    int count;

    void HandleClick()
    {
        count++;
    }
}
mobileblazor

這種專案,使用的是 Microsoft.MobileBlazorBindings.Templates 庫,這個庫封裝了大量的 Razor 元件。

我們可以通過 dotnet 命令來建立這種專案,對應模板如下:

Template Name                                   Short Name            Language    Tags
----------------------------------------------  --------------------  ----------  ------------------------
Experimental Mobile Blazor Bindings App         mobileblazorbindings  [C#]        Blazor/Xamarin.Forms
Experimental Mobile Blazor Bindings Hybrid App  blazorhybrid          [C#]        Blazor/Xamarin.Forms/Web

mobileblazorbindings 不好玩,大家不要試。

我們可以使用命令來建立模板專案:

 dotnet new   blazorhybrid
目錄結構:
H:.
├─HBlazor
│  ├─WebUI
│  │  ├─Pages
│  │  └─Shared
│  └─wwwroot
├─HBlazor.Android
│  ├─Assets
│  ├─Properties
│  ├─Resources
│  └─wwwroot
├─HBlazor.iOS
│  ├─Assets.xcassets
│  ├─Properties
│  └─Resources
│      └─wwwroot
├─HBlazor.macOS
│  ├─Assets.xcassets
│  └─Resources
│      └─wwwroot
└─HBlazor.Windows
    └─wwwroot

但是官方的示例專案有 Bug,而且專案莫名其妙異常,大家試著玩一下就行了。

blazorhybrid

這個原理是 Microsoft.MobileBlazorBindings 封裝了一系列的 razor 元件,然後我編寫 razor 檔案,引用這些元件編寫介面以及動態操作。

測試程式碼(Main.razor):

<ContentView>
    <StackLayout>
        <StackLayout Margin="new Thickness(20)" Orientation="StackOrientation.Horizontal">
            <Label Text="痴者工良" />
            
            <Image Source="@(new FileImageSource { File = "H:/文章/.NET6/mobileblazorbindings/HBlazor/Bugs.jpg" })" />
            <Label Text="@($"Bug - {CounterState.CurrentCount}")" FontSize="40" HorizontalOptions="LayoutOptions.StartAndExpand" />
            <Button Text="解決 Bug" OnClick="@CounterState.IncrementCount" VerticalOptions="LayoutOptions.Center" Padding="10" />
        </StackLayout>

        <BlazorWebView VerticalOptions="LayoutOptions.FillAndExpand">
            <HBlazor.WebUI.App />
        </BlazorWebView>

    </StackLayout>
</ContentView>

注:目前不支援 HTML 標籤 如<br /> ,現在可以使用 Razor 語法,但是還不能直接使用 HTML。 猜測可能是將 Razor 轉換到 Xaml ,所以只能使用裡面已經定義好的元件。怎麼加入 CSS 也是個問題。這也說明了,不支援那些 js !

而 .NET6 博文中提到的 Blazor desktop apps,看介面樣子,應該是網頁版本嵌入的。但是目前還不能嘗試,所以無法測試,跳過。

blazor-macos-768x508

回顧一下跨平臺 UI 應用,主要提到 Xamarin 和 Blazor,而 .NET6 會出現一個新的跨平臺 APP UI 框架,叫 MAUI,.NET MAUI是Xamarin.Forms 的演進,這個在 2020 年時就出現了。這個庫的目的是統一 Xamarin SDK 到 .NET 中,並且能夠與其它專案共享程式碼(如Blazor)。

目前有兩種方式可以嘗試 MAUI:

後者已經提到了,MVU 這種讀者有興趣可以自行測試。

還沒完,雖然 .NET6 中關於 Blazor - 桌面應用的資訊太少,但是我們可以看一下別的框架,例如 LiveSharp

System.CommandLine

以往我們要執行命令,如在 Linux 上檢視程式列表和資源消耗,會使用 top -b -n 1,那麼使用 C# 程式碼表示:

var psi = new ProcessStartInfo("top", "-b -n 1") { RedirectStandardOutput = true };
var proc = Process.Start(psi);

當然還有別的方法,但是似乎有點曲折,並且難以理解。在前面示例程式碼中,把 top 當作一個程式,然後使用引數啟動,但是隻適合那種一次性的程式。例如 top 相對於 Windows 中的工作管理員, -n 1 表示列印一次輸出就結束,如果直接呼叫 top 則是一直動態變化,不會主動結束,這時就會導致出現問題。筆者意思是,這種方式不適合互動式的程式或命令列,如果被呼叫的程式一直不會結束,那麼可能給程式碼帶來問題;像 cat /etc/os-releasels -lah 這些命令,都是一次性輸出的,很容易處理,不會帶來問題。

還要另一種情況就是編寫命令列程式。例如筆者就編寫一個 dotnet tool 工具,名稱為 csys,可以幫助檢視主機的一些資訊,使用者可以輸入命令加上引數,然後判斷要使用的功能:

    public static class Command
    {
        public const string Info = "info";
    }
    
    Console.WriteLine("請輸入命令"); //或者 Main(string[] args) 通過 args 獲取
    string command = "";
    command = Console.ReadLine();
    // netinfo
    if (command == Command.NETINFO)
        NETINFO();

這種方法太笨了,但是沒有更加好的方法可以處理。

為了更加好地跨平臺,.NET6 推出了 System.CommandLine 包,可以更加方便的執行命令和打造命令列程式。

這個庫功能比較多,感興趣的讀者可參考:https://github.com/dotnet/command-line-api

通過這個庫,我們可以很容易打造出像 wget、curl 這樣的命令列程式。

例如,我們 編寫了一個 myapp 的命令列程式,使用者可以這樣執行程式:

$> myapp [parse] --int-option not-an-int --file-option file.txt

要處理這些引數,我們使用 string[]if ,似乎就不太靈活了。System.CommandLine 中有個 Option<T> 可以幫助程式設計師更加好地處理這些引數:

    // Create a root command with some options
    var rootCommand = new RootCommand
    {
        new Option<int>(
            "--int-option",
            getDefaultValue: () => 42,
            description: "An option whose argument is parsed as an int"),
        new Option<bool>(
            "--bool-option",
            "An option whose argument is parsed as a bool"),
        new Option<FileInfo>(
            "--file-option",
            "An option whose argument is parsed as a FileInfo")
    };

例如 new Option<int>,表示如果識別到有 --int-option 這個引數,那麼後面帶的值是數值型別,例如:

--int-option 123

getDefaultValue:() => 42 則設定一個預設值,如果使用者啟動命令時沒有設定,則使用預設值。

如果沒有填寫這個引數,那麼這次 Option<T> 將會使用預設值,例如:

# 不加任何引數
$> myapp

C# 處理這些引數的程式碼:

   // Note that the parameters of the handler method are matched according to the names of the options
   rootCommand.Handler = CommandHandler.Create<int, bool, FileInfo>((intOption, boolOption, fileOption) =>
    {
        Console.WriteLine($"The value for --int-option is: {intOption}");
        Console.WriteLine($"The value for --bool-option is: {boolOption}");
        Console.WriteLine($"The value for --file-option is: {fileOption?.FullName ?? "null"}");
    });

輸出結果:

The value for --int-option is: 42
The value for --bool-option is: False
The value for --file-option is: null

示例程式碼或程式可參考:https://github.com/dotnet/command-line-api/blob/main/docs/Your-first-app-with-System-CommandLine.md

其它更新

其它一些更新主要是文字方面的,筆者將其中一些比較吸睛的資訊整理了一下:

  • Arm64
    .NET5 對 Arm64 版本進行了大量的效能改進,.NET6 繼續提升效能;
    計劃支援在 Windows Arm64 機器上執行 WPF;
    提供了Apple Silicon(Arm64)晶片(本機和模擬)的支援;

  • 容器(Docker)
    優化了容器中 .NET 程式的效能;
    優化了官方映象體積(PGO技術);
    各種方式提升啟動和吞吐量效能;
    更新了基礎映象的版本;

  • System.Numerics
    一組新的數學 API,提高處理數學的效能和根據硬體提升效能;

  • 改善單檔案體積

    釋出的二進位制檔案打包形式可以提升體積大小;但是之前一直說的 AOT 極端優化,還沒有出現;

  • Crossgen2
    Roslyn 是 C# 中用於語法分析和編譯 C# 程式碼的 API 集,可以將 C# 程式碼編譯為 .dll;而 crossgen2 可以編譯成本機程式碼而不是 .dll,crossgen2 是 C# 編寫的,並且可以自舉;crossgen2 僅適用於CoreCLR;

ASP.NET Core

ASP.NET Core 的路線圖獨立於 .NET,大家可以參考:https://themesof.net/ ,這個網站是 Blazor 編寫的,不知道為什麼,網頁內容載入不出來,體驗很不友好呀。也可以看這裡獲得一些路線計劃:https://github.com/dotnet/aspnetcore/issues/27883

.NET6 主要計劃內容:

  • 熱載入
    開發中可以不需要重新編譯,即可對執行中的程式更新 UI 和程式碼,寫 Blazor 和 MVC、API 老方便了;

  • 微型 API

    文件是這樣說的:用更少的程式碼和儀式簡化構建API端點。但是檢視了 Issue 後,發現這個只是學習或者編寫簡單的 API 時可以減少沒必要的 .dll,縮小體積;

  • 單檔案釋出
    構建小型,獨立的高效能應用程式和服務;

  • WebAssembly 提前(AoT)編譯
    釋出時將 Blazor WebAssembly 應用程式中的.NET程式碼直接編譯為 WebAssembly,以顯著提高執行時效能;這樣可以減少一些 .dll 檔案;

  • SPA整合

    不懂這個是什麼,文件說可與最新的現代前端JavaScript框架無縫協作;

  • Blazor hybrid desktop apps

    前面已經提到過,可以使用 Blazor 跟 MAUI 一起開發 UI 程式;

  • HTTP/3

    支援 HTTP/3;提升支援力度;

下面說一下當前 .NET 6 Preview 1 更新的內容。

  • IAsyncDisposable在MVC中的支援

    現在 IAsyncDisposable 介面,可以在控制器,頁面模型和檢視元件上實現以非同步方式處置資源。

  • DynamicComponent

    DynamicComponent 是一個新的內建 Blazor 元件,可用於動態呈現按型別指定的元件。

<DynamicComponent Type="@someType" />

可以使用字典將引數傳遞給渲染的元件:

<DynamicComponent Type="@someType" Parameters="@myDictionaryOfParameters" />

@code {
    Type someType = ...
    IDictionary<string, object> myDictionaryOfParameters = ...
}
  • ElementReference

    ElementReference 是一個物件,用於傳遞 HTML 元素引用,在 Js 中我們可以使用 document.getElementById('someId') 來定位元素,但是在 Blazor 中許多元件動態組合,很難確定 ID 都是唯一的或者準確定位。為了解決這個問題,Blazor通過 @refelement標籤 和ElementReferencestruct 來處理。感興趣的讀者可以檢視 Passing HTML element references
    現在 ElementReference 為 InputCheckboxInputDateInputFileInputNumberInputSelectInputText,和InputTextArea 等輸入元件提供了更加方便的處理方式,例如將 UI 焦點設定在這些輸入元件上。

  • 可空引用型別註釋
    這個是非常好的規範約束,現在 ASP.NET Core 中的各個部分都加上了這些註釋,可以更加容易地提升專案的編譯安全性。選擇使用可為空的註釋的專案可能會從ASP.NET Core API中看到新的生成時警告。

另外 EFCore 也進行了一些更新,沒啥影響,這裡就不提了。

相關文章