ASP.NET Core Blazor 在元件 Component 上的注入各種服務的存留期研究
在這篇文章所提到的專案原始碼,可以從 GitHub 下載
底下將會是關於抽象型別與具體實作類別和 Startup 類別的程式碼
namespace BlazorScopedSingleton
{
public interface IMessageTransient
{
string Hash();
}
public interface IMessageScoped
{
string Hash();
}
public interface IMessageSingleton
{
string Hash();
}
public class MessageTransient : IMessageTransient
{
public string Hash()
{
return $"MessageTransient : {this.GetHashCode()}";
}
}
public class MessageScoped : IMessageScoped
{
public string Hash()
{
return $"MessageScoped : {this.GetHashCode()}";
}
}
public class MessageSingleton : IMessageSingleton
{
public string Hash()
{
return $"MessageSingleton : {this.GetHashCode()}";
}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// 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)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
services.AddTransient<IMessageTransient, MessageTransient>();
services.AddScoped<IMessageScoped, MessageScoped>();
services.AddSingleton<IMessageSingleton, MessageSingleton>();
}
// 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();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}
在上面的程式碼中,將會建立三個介面並且使用這三個介面分別實作三個具體實作類別,從這些介面與類別名稱,可以充分表達是要進行 DI 存留期 Transient , Scoped , Singleton 的測試,了解到這些相依性注入的存留期在 Blazor 中表現行為為何。
這裡所建立的 Blazor 專案為 Serivce 端的 Blazor 專案。
首先,將會建立一個名為 ForContainer 的 Component 元件,其程式碼如下所示
@page "/ForContainer"
@inject IMessageTransient messageTransient1
@inject IMessageTransient messageTransient2
@inject IMessageScoped messageScoped1
@inject IMessageScoped messageScoped2
@inject IMessageSingleton messageSingleton1
@inject IMessageSingleton messageSingleton2
<h3>ForContainer</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>
@code {
}
在這裡,將會使用
@inject
語法,將不同介面所需要的服務,注入到這個元件中,其中,每個介面都會注入兩次到不同的變數內,以便觀察有何變化。
現在可以執行專案,並且切換網址列為 https://localhost:5001/ForContainer
底下為第一次執行的結果,從這裡可以看的出來,當使用 Transient 存留期註冊的服務,只要每次注入這個服務的時候,就會得到不同的物件,因為 DI Container 容器會立即產生出的新的執行個體出來;當使用 Scoped 存留期,因為是在同一個 Connection ,所以,會得到同一個執行個體物件,同樣的,Singleton 存留期,在這次執行過程中,也是得到相同的物件。
現在,在瀏覽器上開啟一個新的標籤頁次,輸入同樣的網址,看看執行結果
當然,對於 Transient 存留期,同樣的會產生兩個嶄新的物件,而對於 Scoped 的注入請求,因為在這裡是一個新的連線,因此,在這次新的連線過程中,多次注入同一個介面,會得到同一個物件,這點也是沒有問題;而對於 Singleton 存留期,因為這個專案還在執行中,所以,將會得到與上面同樣的物件,沒有任何變化。
此時,再來產生一個新的元件,在這個元件中,將會使用剛剛設計的 ForContainer 元件兩次,現在,來看看這樣會有甚麼執行結果。
@page "/ForMultipleComponent"
@using BlazorScopedSingleton.Pages
<h3>ForMultipleComponent</h3>
<ForContainer />
<ForContainer />
@code {
}
這裡將會打開 https://localhost:5001/ForMultipleComponent 網址,執行結果如下面螢幕截圖
很清楚的,只要這個專案還在執行階段,只要使用 Singleton 方式來注入,不論是單一元件,還是開多個網頁甚至使用巢狀元件的方式,都會得到同一個物件,這裡的表現符合預期;而對 Transient 而言,也是一樣,只要每次注入的時候,都會得到一個新的物件;至於 Scoped 這樣的存留期,將過這裡的測試,得到只要是在同一個連現階段,不論是對於單一元件或者同樣的元件要顯示多次,都會在同一個連線過程中,得到同一個物件。
現在,再來重新整理這個網址 https://localhost:5001/ForMultipleComponent 網址,執行結果如下面螢幕截圖,這樣的結果也是符合預期的。
更多關於 Blazor 教學影片,可以參考 Blazor 教學影片播放清單 或者 Blazor 快速體驗教學影片撥放清單。也歡迎訂閱本 .NET / Blazor / Xamarin.Forms 影片頻道 。
當在使用 Blazor 進行專案開發的時候,可以使用 ASP.NET Core 提供的相依性注入服務功能,此時僅需要宣告與建立所需要的抽象介面與具體實作類別,接著在 Startup 類別內的 ConfigureServices 方法內,進行註冊這些抽象介面與類別到相依性入 DI Container 容器內;當想要使用這些服務的時候,便可以在所建立的元件 Component 內,使用
@inject
語法便可以將這些服務注入到該元件內來使用。