2019年12月13日 星期五

從空白專案來建立 ASP.NET Core Blazor 應用程式 - 了解 Blazor 運作方式

從空白專案來建立 ASP.NET Core Blazor 應用程式 - 了解 Blazor 運作方式

更多關於 Blazor 教學影片,可以參考 Blazor 教學影片播放清單 或者 Blazor 快速體驗教學影片撥放清單。也歡迎訂閱本 .NET / Blazor / Xamarin.Forms 影片頻道 。


想要了解 Blazor 專案是如何運作的,最佳的方式,就是從無到有,做出一個最為精簡的 Blazor 應用程式,在這篇文章中,將會說明如何進行這樣的設計工作,並且在不使用 JavaScript 程式語言的狀況下,便可以僅使用 HTML / C# 來設計出一個具有互動運作的網頁。
在這篇文章所提到的專案原始碼,可以從 GitHub 下載

建立一個空白的 ASP.NET Core 空白專案

想要進行這樣的專案開發練習,可以參考底下的操作步驟
  • 打開 Visual Studio 2019 開發工具
  • 當 [Visual Studio 2019] 對話窗出現之後,點選右下方的 [建立新的專案] 按鈕
  • 在 [建立新專案] 對話窗內,請找出 [ASP.NET Core Web 應用程式] 這個專案開發範本,並且點選這個專案開發範本
  • 請點選右下角 [下一步] 按鈕
  • 出現 [設定新的專案] 對話窗,輸入適當的 [專案名稱] 、 [位置] 、 [解決方案名稱],完成後,請點選右下角 [建立] 按鈕
    在這個範例程式碼中,將會建立一個 BlazorFromeEmpty 專案名稱
  • 此時將會看到 [建立新的 ASP.NET Core Web 應用程式] 對話窗,請在清單中選擇 [空白] 這個專案範本,在此將要建立一個空白的 ASP.NET Core 的專案,若無,請點選右下角的 [建立] 按鈕
  • 此時,這個 空白 ASP.NET Core 專案已經建立完成
此時,這個專案的結構如下圖所示
這個專案內很簡單的僅有 Program.cs 與 Startup.cs 這兩個檔案
Programs.cs 的檔案內容如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace BlazorFromeEmpty
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}
對於 Program 這個類別,將會與所有其他 ASP.NET Core 專案相同,例如:MVC, Web API, Razor Page
Startup.cs 的檔案內容如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace BlazorFromeEmpty
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
    }
}
在這個 Startup 類別內,可以看到在 ConfigureServices 方法內,沒有設計任何程式碼
現在,可以執行這個專案,看看會出現甚麼內容?
如同在 Configure 方法內的 app.UseEndpoints 敘述所定義的,這裡網站專案,僅能夠顯示 Hello World! 這樣的文字在瀏覽器上。

開始重構,變成一個 Blazor 專案

對於 Program.cs 這個檔案,並不需要做任何的修正,而對於 Startup.cs 這個檔案,則需要加入一些程式碼
public void ConfigureServices(IServiceCollection services)
{
    #region 在這裡要宣告所要使用的服務
    services.AddRazorPages();
    services.AddServerSideBlazor();
    // 設著將這行註解起來,並且執行,看看會發生甚麼問題?
    services.Configure<RazorPagesOptions>(options => options.RootDirectory = "/");
    #endregion
}
在 ConfigureServices 方法內,將會在這個 ASP.NET Core 專案內啟用 Blazor 會使用到的服務
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    #region 請加入這兩行敘述
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    #endregion

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        #region 將原先空白專案中的敘述,註解起來
        //endpoints.MapGet("/", async context =>
        //{
        //    await context.Response.WriteAsync("Hello World!");
        //});
        #endregion

        #region 請在這裡加入 Blazor 會用到的路由設定功能
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
        #endregion
    });
}
在這裡要修改、調整、新增的程式碼,都特別有使用 #region ... #endregion 標示出來

加入 Blazor 會用到的檔案

現在要開始建立 Blazor 會用到的最少檔案,這裡僅需要三個檔案,就可以建立一個使用 HTML / C# 且具有互動效果的網頁,更美妙的是,整個過程,完全不需要呼叫呼叫 JavaScript。
首先,要建立兩個 Blazor 必備用到的檔案 _Host.cshtml App.razor
請先建立 _Host.cshtml
  • 滑鼠右擊 專案 節點,選擇 [加入] > [新增項目] 功能項目
  • 當 [新增項目] 對話窗顯示之後,請找到並且選擇 [Razor 頁面] 這個項目名稱
  • 在左下方的名稱欄位中,輸入該 Razor 頁面 的名稱 : _Host.cshtml
  • 最後,點選右下角的 [新增] 按鈕
請使用底下的 Razor 頁面的標記與程式碼寫入到這個檔案內
@page "/"
@namespace BlazorFromeEmpty
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@{
    Layout = null;
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blazor 從無到有</title>
    <base href="~/" />
</head>
<body>

    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>

    <script src="_framework/blazor.server.js"></script>
</body>
</html>
接著要建立 App.razor
  • 滑鼠右擊 專案 節點,選擇 [加入] > [新增項目] 功能項目
  • 當 [新增項目] 對話窗顯示之後,請找到並且選擇 [Razor 元件] 這個項目名稱
  • 在左下方的名稱欄位中,輸入該 Razor 元件 的名稱 : App.razor
  • 最後,點選右下角的 [新增] 按鈕
請使用底下的 Razor 元件的標記與程式碼寫入到這個檔案內
@using Microsoft.AspNetCore.Components.Routing

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" />
    </Found>
    <NotFound>
        <p>Sorry, there's nothing at this address.</p>
    </NotFound>
</Router>
最後要來建立第一個 Blazor 元件,也就是首頁頁面 Index.razor
  • 滑鼠右擊 專案 節點,選擇 [加入] > [新增項目] 功能項目
  • 當 [新增項目] 對話窗顯示之後,請找到並且選擇 [Razor 元件] 這個項目名稱
  • 在左下方的名稱欄位中,輸入該 Razor 元件 的名稱 : Index.razor
  • 最後,點選右下角的 [新增] 按鈕
請使用底下的 Razor 元件的標記與程式碼寫入到這個檔案內
@page "/"
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web

<h1>從空白 ASP.NET Core 來建立 Blazor 應用程式</h1>

<input @bind-value="Message" @bind-value:event="oninput" />
<p>@Message</p>
<button @onclick="clicked">OK</button>

@code{
    string Message { get; set; } = "Hi 你好";
    void clicked()
    {
        Message = "Click Button";
    }
}

執行看結果

請執行這個專案
這裡將會看到如上圖的畫面,其中該網頁上會有一個文字輸入盒、一個標籤文字、一個按鈕
現在,請在文字輸入盒輸入任何文字,此時,將會看到底下的標籤文字將會出現剛剛顯示的文字內容,這就是使用到 Blazor 內的絕佳特色功能,雙向資料綁定
最後,請按下按鈕,此時,將會觸發該按鈕所綁定的 C# 委派事件方法,並且會重新設定文字輸入盒與標籤文字內容,如上圖所示。
好了,這裡就是 Blazor 應用程式所需要的最簡單的專案內容




2019年12月12日 星期四

ASP.NET Core Blazor 單向與雙向資料綁定

ASP.NET Core Blazor 單向與雙向資料綁定

更多關於 Blazor 教學影片,可以參考 Blazor 教學影片播放清單 或者 Blazor 快速體驗教學影片撥放清單。也歡迎訂閱本 .NET / Blazor / Xamarin.Forms 影片頻道 。


幾乎所有的 GUI 開發框架,都需要具備有資料綁定 Data Binding 這樣的功能,若正在使用的開發框架 Framework 沒有提供類似這樣的功能,則十分建議可以不用再繼續使用了;而當然,對於強大的 Blazor 開發框架,也是具有這樣的特性,因此,將會透過這篇文章中的兩個頁面範例,進行展示出來這樣好用的功能是要如何來使用。
在這篇文章所提到的專案原始碼,可以從 GitHub 下載

單向資料綁定 Oneway Data Binding

在 Blazor 中所謂的單向資料綁定,指的是當 .NET CLR 的物件有異動的時候,將會進行更新到 UI 上的,對於像是在 MVVM Model View ViewModel 設計模式下,對於單向資料綁定可以使用於當 ViewModel 內的屬性有異動的時候,將會更新 View 上的顯示內容,或者是僅有當 View 上的顯示內容有異動的時候,才會更新到 ViewModel 內的屬性上,反之則不會成立。
想要進行這樣的專案開發練習,可以參考底下的操作步驟
  • 打開 Visual Studio 2019 開發工具
  • 當 [Visual Studio 2019] 對話窗出現之後,點選右下方的 [建立新的專案] 按鈕
  • 在 [建立新專案] 對話窗內,請找出 [Blazor 應用程式] 這個專案開發範本,並且點選這個專案開發範本
  • 請點選右下角 [下一步] 按鈕
  • 出現 [設定新的專案] 對話窗,輸入適當的 [專案名稱] 、 [位置] 、 [解決方案名稱],完成後,請點選右下角 [建立] 按鈕
    在這個範例程式碼中,將會建立一個 BlazorDataBinding 專案名稱
  • 此時將會看到 [建立新的 Blazor 應用程式] 對話窗,這裡可以根據當時開發專案的需要,自行決定是否有調整 Blazor 專案的其他特性,若無,請點選右下角的 [建立] 按鈕
  • 此時,這個 Blazor 專案已經建立完成
現在可以開始來建立一個單向資料綁定的頁面,練習如何設計單向資料綁定的程式設計方法:
  • 滑鼠右擊 [Pages] 資料夾,選擇 [加入] > [新增項目] 功能項目
  • 當 [新增項目] 對話窗顯示之後,請找到並且選擇 [Blazor 元件] 這個項目名稱
  • 在左下方的名稱欄位中,輸入該 Blazor 元件的名稱
    這裡將會建立一個 OnewayBinding 新 Blazor 元件
    Blazor 元件檔案名稱都會使用 .razor 作為其副檔名
  • 最後,點選右下角的 [新增] 按鈕
請將底下的 Blazor 頁面之標記與程式碼,寫入到這個檔案內
@page "/OnewayBinding"
@using System.Threading
@using System.Threading.Tasks

<h3>單向資料綁定</h3>

<div>
    @Message
</div>
<buttn class="btn btn-outline-primary"
       @onclick="Start">開始動作</buttn>
<div class="@background" style="height:300px;border:none">
    @background
</div>

@code {
    string Message = "尚未接收到任何訊息";
    string background = "bg-transparent";
    int index = 0;
    CancellationTokenSource cts = new CancellationTokenSource();
    CancellationToken token;

    void Start()
    {
        Message = "已經接收到要開始動作指令了";
    }

    protected override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            CancellationToken token = cts.Token;
            ShowCycle(token);
        }
        return Task.FromResult(0);
    }
    async Task ShowCycle(CancellationToken token)
    {
        while(true)
        {
            ShowColor();
            StateHasChanged();
            await Task.Delay(900);
            if(token.IsCancellationRequested)
            {
                break;
            }
        }
    }
    void ShowColor()
    {
        switch (index)
        {
            case 0:
                background = "bg-primary";
                break;
            case 1:
                background = "bg-secondary";
                break;
            case 2:
                background = "bg-success ";
                break;
            case 3:
                background = "bg-danger";
                break;
            case 4:
                background = "bg-warning";
                break;
            case 5:
                background = "bg-info";
                break;
            case 6:
                background = "bg-light";
                break;
            case 7:
                background = "bg-dark";
                break;
            case 8:
                background = "bg-white";
                break;
            default:
                break;
        }
        index++;
        if (index > 8) index = 0;
    }
}
在這個頁面中,將會宣告一個 Message 變數,並且透過 Razor 語法,將這個變數顯示在 HTML 標記內,如同這樣 <div>@Message</div> ,如此,當 Message 變數值有異動的時候,就會變更 HTML 上面的內容,也就達成了更新網頁內容的目的;這一切的效果都會透過 Blazor 內建的資料綁定機制來完成,而這裡所使用的技巧就是單向 Oneway Data Binding 資料綁定技術,最重要的是,所有的過程,開發者都不再需要透過 JavaScript 或者相關 JS 開發框架 Angular / React / Vue 等等來達成。
為了要能夠呈現出當 Message 變數有變動,網頁會如何顯示,這裡將會標記一個 <button> 標記,並且使用 @onclick="Start" 這樣的語法來宣告,當這個按鈕被觸發的時候,將會執行該頁面中的 Start 方法,在 Start() 方法內,將會執行 Message = "已經接收到要開始動作指令了"; 敘述,也就是說 Message 這個變數值已經變動了,此時,可以觀察網頁畫面,就會看到這個頁面上的文字,會從 [尚未接收到任何訊息] 轉變成為 [尚未接收到任何訊息] ,這一切發生的效果是不是很神奇呀。
另外,在這個頁面中,也會使用到 Blazor Componet Lifecycle 元件生命週期的事件:OnAfterRenderAsync ,該事件會當整個網頁已經顯示在瀏覽器上的時候,會被觸發執行,在這個事件委派方法內,將會執行 ShowCycle() 方法,這是一個 Fire and Forget 射後不理 的非同步工作方法。
在 ShowCycle 方法內,每隔 0.9 秒的時間,變更 background 變數的數值,這個變數將會綁定到網頁上的 div 標籤的 class 屬性上,也就是將這個變數字串內容,設定為各種 Bootstrap 4 的背景顏色類別宣告,這樣將會達成每隔 0.9 秒的時間,就會更換這個 div 標記內的背景顏色效果;因為該 div 的 class 宣告值有異動,透過 Blazor 的重新渲染機制,將會更新網頁中 DOM 內容,造成顏色有變化效果。
不過,要特別注意的是,當 background 字串值變動之後,將會需要呼叫 StateHasChanged() 這個方法,該方法將會 通知組件其狀態已更改。如果適用,這將導致重新渲染組件;也就是說,若沒有加入這個方法呼叫,每隔 0.9 秒將不會有任何背景顏色的變化出來。
底下將會是執行後的螢幕畫面
一開始顯示網頁的時候,在按鈕的上方文字會顯示為 : 尚未接收到任何訊息,而在最下方的區塊,將會不斷地變換背景顏色。
現在,可以點選螢幕上的按鈕,此時該按鈕的上方文字將會顯示為 : 已經接收到要開始動作指令了
這一切的成果,都將會透過 Blazor 單向資料綁定來做到。

雙向資料綁定 Twoway Data Binding

現在,要來體驗 雙向資料綁定 Twoway Data Binding,在 Blazor 中所謂的雙向資料綁定,指的是當 .NET CLR 的物件有異動的時候,將會進行更新到 UI 上,而當網頁上綁定的值有變動的時候,例如,使用者在該 UI 上輸入了任何資料,此時,將會更新到 .NET CLR 的變數上,反之亦然,也就是當 .NET CLR 變數有變動的時候,也會更新到 HTML 網頁上 DOM 內容。
現在可以開始來建立一個雙向資料綁定的頁面,練習如何設計雙向資料綁定的程式設計方法:
  • 滑鼠右擊 [Pages] 資料夾,選擇 [加入] > [新增項目] 功能項目
  • 當 [新增項目] 對話窗顯示之後,請找到並且選擇 [Blazor 元件] 這個項目名稱
  • 在左下方的名稱欄位中,輸入該 Blazor 元件的名稱
    這裡將會建立一個 TwowayBinding 新 Blazor 元件
    Blazor 元件檔案名稱都會使用 .razor 作為其副檔名
  • 最後,點選右下角的 [新增] 按鈕
請將底下的 Blazor 頁面之標記與程式碼,寫入到這個檔案內
@page "/TwowayBinding"

<h3>雙向資料綁定</h3>

<input type="text" value="@Message1" />
<div>@Message1</div>
<input type="text" @bind="Message2" />
<div>@Message2</div>
<input type="range" class="form-control-range" max="8" min="0" step="1"
       @bind="Index" @bind:event="oninput" />
<div class="@background" style="height:200px;border:none">
    @background
</div>
@code {
    string Message1 = "Message1";
    string Message2 = "Message2";
    string background = "bg-transparent";
    private int index;

    public int Index
    {
        get { return index; }
        set
        {
            index = value;
            ShowColor();
        }
    }

    void ShowColor()
    {
        switch (Index)
        {
            case 0:
                background = "bg-primary";
                break;
            case 1:
                background = "bg-secondary";
                break;
            case 2:
                background = "bg-success ";
                break;
            case 3:
                background = "bg-danger";
                break;
            case 4:
                background = "bg-warning";
                break;
            case 5:
                background = "bg-info";
                break;
            case 6:
                background = "bg-light";
                break;
            case 7:
                background = "bg-dark";
                break;
            case 8:
                background = "bg-white";
                break;
            default:
                break;
        }
    }
}
在這個頁面中,將會同樣的會展現兩個功能特色,在上半部會有兩個 input 文字輸入盒,而在這兩個 input 文字輸入盒的下方,將會有 div 標籤,將綁定在 input 文字輸入盒內的文字內容,顯示在網頁上;在這兩個 input 宣告標記中,可以看到使用了不同的宣告語法,在前者將會把 HTML 內的這個 input 標記之 value 屬性,也就是使用這樣的 value="@Message1" 宣告語法,綁定到 .NET CLR 的 Message1 這個變數內,而這樣的做法將會是屬於單向資料綁定,也就是說,若使用者在網頁上的第一個 input 上輸入任何文字,將不會更新到 Message1 這個變數上,也就是對於 <div>@Message1</div> 標記而言,顯示的內容都是相同的,因為 Blazor 不會透過 DOM 內容,來變更這個 div 內的文字內容。
對於第二個 input 標記而言,將會使用了 @bind="Message2" 這樣的宣告語法,這是一個雙向資料綁定的宣告語法,也就是說,當使用者在第二個 input 文字輸入盒,輸入了任何文字,將會造成下方的 <div>@Message2</div> 標記也會更新,因為,當使用者變更 input 輸入文字內容,就會同時更新 .NET CLR Message2 物件內的值,而當這個 Message2 的物件值變動後,就會透過資料綁定機制,更新了 DOM 內 <div>@Message2</div> 標記內容,如此,將會造成可以顯示出使用者最新輸入的文字內容了。
在最下方的 input 標記,宣告型別為 type="range" 來形成一個 滑動桿 輸入控制項, 這裡宣告了 @bind="Index" 語法,讓滑動桿輸入的值,可以使用雙向資料綁定的方式,綁定到 .NET CLR 內的 Index 變數內,另外,為了要能夠做到當滑動桿的值又變化的時候,可以立即觸發雙向資料綁定的效果,而不再使用滑鼠點擊到網頁的其他地方,來觸發雙向資料綁定的動作,因此,在這裡將會使用 @bind:event="oninput" 這樣的宣告方式,設定了只要滑動桿的值有變化的時候,立即會觸發雙向資料綁定動作。
當因為雙向資料綁定機制,導致 .NET CLR 的 Index 變數有變動的時候,將會使得該屬性 C# Property 之設定存取子被執行,這裡將會把 index 這個支援欄位的變數值進行更新,接著,將會呼叫 ShowColor 方法,如此,將會造成最下方的 div 標記的背景顏色有所變更。
這裡可以觀察到,這裡將沒有呼叫 StateHasChanged() 這個方法,但是,同樣的會進行更新 DOM 的內容,也就是會變更 HTML 顯示內容。
底下將會是執行後的螢幕畫面
當一開始執行的時候,最上方的兩個文字輸入盒,都會顯示預設的 .NET CLR 變數值,這是因為,雙方都具有單向綁定的特性。
現在,在第一個文字輸入盒內,輸入任何文字之後,發現到其下方的 div 標記內的文字,沒有同步更新,這是因為第一個 input 使用的是單向資料綁定的宣告語法。
對於第二個 input 文字輸入盒,在此輸入任何文字,便可以看到底下的 div 區塊內的文字,有同步更新,這是因為這裡使用了雙向資料綁定的宣告語法。
接著請使用滑鼠滑動滑動桿,便可以看到滑動桿的下方 div 區塊的背景顏色,會不斷的變化顏色




2019年12月11日 星期三

ASP.NET Core Blazor dependency injection 之元件的存留期

ASP.NET Core Blazor dependency injection 之元件的存留期

更多關於 Blazor 教學影片,可以參考 Blazor 教學影片播放清單 或者 Blazor 快速體驗教學影片撥放清單。也歡迎訂閱本 .NET / Blazor / Xamarin.Forms 影片頻道 。


接續上篇文章 ASP.NET Core Blazor 在元件 Component 上的注入各種服務的存留期研究,實際進行 ASP.NET Core 中的三種存留期的注入使用方式與表現狀態,在這篇文章中,將來檢視 Blazor 中的 元件 Component Scoped 具範圍的行為表現。
在這篇文章所提到的專案原始碼,可以從 GitHub 下載
在這裡將會建立一個 Blazor 伺服器端的專案,並且在 Pages 資料夾下,建立一個 Blazor 元件 , DifferentInjection ,其程式碼如下:
@page "/DifferentInjection" @inherits OwningComponentBase<IMessageScoped>
  @inject IMessageTransient messageTransient1 @inject IMessageTransient
  messageTransient2 @inject IMessageScoped messageScoped1 @inject IMessageScoped
  messageScoped2 @inject IMessageSingleton messageSingleton1 @inject
  IMessageSingleton messageSingleton2

  <h3>DifferentInjection</h3>

  <div class="bg-info">
    messageTransient1 的物件為 @messageTransient1.Hash()
  </div>
  <div class="bg-warning">
    messageTransient2 的物件為 @messageTransient2.Hash()
  </div>
  <div class="bg-info">messageScoped1 的物件為 @messageScoped1.Hash()</div>
  <div class="bg-warning">messageScoped1 的物件為 @messageScoped2.Hash()</div>
  <div class="bg-info">
    messageSingleton1 的物件為 @messageSingleton1.Hash()
  </div>
  <div class="bg-warning">
    messageSingleton2 的物件為 @messageSingleton2.Hash()
  </div>
  <div />
  <div class="btn btn-outline-danger">
    messageTransient3 的物件為 @messageTransient3.Hash()
  </div>
  <div class="btn btn-outline-success">
    messageScoped3 的物件為 @messageScoped3.Hash()
  </div>
  <div class="btn btn-outline-dark">
    messageSingleton3 的物件為 @messageTransient3.Hash()
  </div>
  <div class="btn btn-outline-warning">
    OwningComponentBase 的物件為 @Service.Hash()
  </div>

  @code { [Inject] public IMessageTransient messageTransient3 { get; set; }
  [Inject] public IMessageScoped messageScoped3 { get; set; } [Inject] public
  IMessageSingleton messageSingleton3 { get; set; } }</IMessageScoped
>
在上面使用了兩個新的注入技巧,一個是在最上面使用了 @inherits OwningComponentBase<IMessageSingleton> 語法,這樣將會使用了元件具範圍的方式來注入該物件,而且,一個頁面上僅能夠宣告一個,不能多個,這是為什麼呢?請大家思考看看。
另外一個注入物件的方式,那就是宣告一個屬性 Property,並且使用 Inject 屬性 Attribute 來標示建立的 C# Property,這樣也可以達到注入物件的效果,現在來看看執行效果:
這裡是第一次執行的結果
不論是使用 @inject 語法,或者使用 [inject] attribute 屬性宣告方式,都可以達到注入物件的效果,而且所注入的物件,也都是按照當初註冊的存留期設定方式來表現;對於最後一個元件具範圍,需要使用 Service 這個變數來存取注入的物件,例如,在這裡是使用 @Service.Hash() 這樣的方式,而且從螢幕截圖的最下方可以看到(黃色底、黑色文字),這裡並沒有使用這次請求 Request 所使用的 Scoped 物件,而是獲得另外一個新的物件,雖然當初宣告的語法為 OwningComponentBase<IMessageScoped> 是要注入一個 Scoped 的物件,不過,這裡是享有 元件具範圍 Component Scoped 的特性。
底下為重新整理同一個網頁的執行結果
其中,因為產生一個新的 Request,所以,對於 Scoped 的存留期的注入,將會重新配置一個新的物件,並且不論使用哪種注入語法;對於 Singleton 的存留期注入,得到的還是同一個物件,與尚未整理前看到的相同。