前言

相依性注入是一種可以存取在中央設定的服務的技術,註冊的服務可以直接在 razor 元件內使用,Blazor 跟 ASP.NET Core 上的 DI 稍微有些不同,如果還不清楚什麼是相依性注入(DI)的可以先閱讀這篇文章 ASP.NET Core中的相依性插入

預設服務

在 Blazor 有三個服務是系統預先這註冊的

  • HttpClinet 提供傳送 Http 請求以及接收回應的方法,在 Blazor WebAssembly 預先註冊的,但是在 Blazor Server 則沒有,所以想要在 Server 專案呼叫API需要先到Program.cs 註冊才能使用

  • IJSRuntime 提供 JavaScript 執行階段的服務

  • NavigationManager 包含使用 URI 和瀏覽狀態的協助程式

服務留存期

  • Scoped 針對 Web 應用程式,限定範圍的存留期表示每個用戶端要求 (連線) 建立服務一次,比較白話的說法是同一個人都會用到相同的執行個體

在 Blazor WebAssembly 沒有這個Scoped的概念,使用 Scoped 會等同於使用 Singleton

  • Singleton 第一次被注入時建立執行個體,以後就用同一個執行個體

  • Transient 每次從服務容器要求暫時性存留期服務時都會建立它們。 此存留期最適合用於輕量型的無狀態服務。 也就是說每一次的注入的都是新的執行個體

WebAssembly DI 實作

  1. 建立一個 Blaozr WebAssembly 專案 BlazorApp.DI

  2. 建立 Service 資料夾,並加入 OrderService.cs 類別,用來模擬一個服務

  3. 寫一個取得訂單的方法

1
2
3
4
5
6
7
8
 /// <summary>
 /// 取得訂單編號
 /// </summary>
 /// <returns></returns>
 public string GetOrderNo()
 {
     return "20221003";
 }
  1. index.razor 引用剛剛寫的服務
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@page "/"
@using BlazorApp.DI.Service
@inject OrderService OrderService

<PageTitle>Index</PageTitle>

<h1>訂單編號 : @OrderService.GetOrderNo()</h1>

<h2>HashCode @OrderService.GetHashCode()</h2>


Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />
  1. 服務註冊 如果直接執行會發現網頁一開就跟你說發生錯誤
1
Cannot provide a value for property 'OrderService' on type 'BlazorApp.DI.Pages.Index'. There is no registered service of type 'BlazorApp.DI.Service.OrderService'.

因為 Blazor 找不到這一個服務,要在元件內使用我們要先為該服務做註冊,在 Program.cs 內註冊服務

1
builder.Services.AddScoped<OrderService>();
  1. 執行專案 執行後就會順利的看見我們寫的訂單編號 20221003,HashCode 則都會是相同的因為對於 WebAssembly 專案來說 AddScope 等同於 AddSingleton

Server DI 實作

方法都和前面的 WebAssembly 相同,唯獨在結果的部分不同,在 Server 專案內使用 AddScoped,每一次發出 Request 時,頁面上所顯示的 HashCode 都會不同,原因是每一次的 請求 都會注入一個的執行個體 如果把 Program.cs 內的註冊方法改成 AddSingleton 就會得到和 WebAssembly 一樣的結果

小結

依賴注入的部分是 ASP.NET Core 很重要的一個環節,務必了解物件存留期的概念以及在兩種 Blazor 專案上的差異,如果有時間順便想想看為什麼在 WebAssembly 會沒有 Scoped 的概念,下一個章節介紹 表單驗證的作法