首頁 > 軟體

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

2021-02-19 09:30:10


最近 .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 查詢下載連結,發現不開代理下載不了,各位請注意。

.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 吧。

迴歸正題,.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++;
    }
}

這個原理是 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,看介面樣子,應該是網頁版本嵌入的。但是目前還不能嘗試,所以無法測試,跳過。

回顧一下跨平臺 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 也進行了一些更新,沒啥影響,這裡就不提了。


IT145.com E-mail:sddin#qq.com