前面說過自己建立的Service都必須在Startup.cs
(Blazor Server)或Program.cs
(Blazor WebAssemlby)註冊,但有些基本Service就不用自己做了。
目前Blazor提供內建的Service有三個,分別為:
HttpClient
:處理http請求,生命週期為Scoped(注意:只有Blazor WebAssembly有提供,Blazor Server必須自己註冊)
IJSRuntime
:提供Javascript runtime物件處理JS功能,Blazor WebAssembly生命週期為Singleton
,Blazor Server生命週期為Scoped
NavigationManager
:處理路由導向和狀態Blazor WebAssembly生命週期為Singleton,Blazor Server生命週期為Scoped
生命週期指的就是Component存活的時間,除了Singleton
跟Scoped
,還有一種Transient
。
Singleton
是指從程式啟動到結束都只會有一個實體,所有Component共用一個實體。
Transient
則是每次使用該Component時,都會產生一個新實體。
Scoped
較為特別,Blazor Server跟Blazor WebAssembly模式不相同,Blazor Server的Scoped
是指每次HTTP請求都會產生一個新的實體,但Component之間通過SingalR傳遞不會產生,微軟文件說明「Blazor WebAssembly目前沒有DI的概念,Scoped
相當於Singleton
」。
不過筆者當初看了上述說明也是霧煞煞,直到看了一個影片用GUID示範後才有所明白,我們就來試試看。
首先建立一個介面IGuidService
,裡面只有一個型別為字串的屬性uid
,接著建立類別GuidService
並實作屬性以及建構子讓uid
承接GUID,再去Startup.cs
的ConfigureServices
使用AddTransient
註冊。
然後建立一個Guid.razor
Component,裡面只有三行分別定義路由、注入服務以及顯示GUID字串,因為這案例很簡單所以沒用到ComponentBase,所以需要在_Import.razor
加入@using BlazorServer.Services
,最後為了切換方便,在NavMenu.razor
定義一組NavLink指向剛才建立的Guid.razor
。
啟動後不論在Post及Guid頁面切換,或是重整頁面,都可以看到產生全新的一組GUID,這就是Transient
的特性:每次切換都產生新的實體。
接著將註冊方式改為Singleton
,可以看到就算重整網頁,也都是同一組GUID,這就是Singleton
的特性:程式啟動到結束都只會有一個實體。
最後將註冊方式改為Scoped
,切換到Post頁面再切回來,還是同一組GUID,但重整頁面時就會產生新的一組,這就是Scoped
的特性:每次產生HTTP請求都會有新的實體,Component之間則不會產生新實體。
上述的例子是以Blazor Server進行,若以Blazor WebAssembly進行,則Singleton
會產生跟Blazor Server不同的情況,原因就是Blazor WebAssembly沒有伺服器,每次重整網頁都會將程式下載到瀏覽器,這是一個全新的HTTP請求,所以Singleton
跟Scoped
都是只要一重整網頁就會產生新的實體。
註:筆者為了方便省略影片中某些內容,有興趣的人可以再研究
Ref: Blazor Course - Use ASP.NET Core to Build Full-Stack C# Web Apps
Ref: ASP.NET Core Blazor dependency injection