標籤:space enum tps ado ons startup es2017 edit 空間
07、NetCore2.0外掛程式架構之生命週期
NetCore2.0外掛程式架構是如何管理外掛程式的生命週期的?生命週期有哪幾類,又是在哪些情境下應用的呢?
一、生命週期的分類
我們可以查看系統DI(依賴倒置)的開原始碼:
namespace Microsoft.Extensions.DependencyInjection{ public enum ServiceLifetime { Singleton, Scoped, Transient }}
從源碼可以看出,DI架構支援三種生命週期管理員模式
單例模式,服務在第一次請求時被建立,其後的每次請求都沿用這個已建立的服務。我們不用再自己寫單例了。
範圍模式,服務在每次請求時被建立,整個請求過程中都貫穿使用這個建立的服務。比如Web頁面的一次請求。
瞬態模式,服務在每次請求時被建立,它最好被用於輕量級無狀態服務。
二、重現三種生命週期的應用情境
首先我們建立三個服務,用來提供GUID。
using System;namespace LifetimeOfDI{ public interface IGuidService { Guid Id(); } public interface ITransientService : IGuidService { } public interface IScopedService : IGuidService { } public interface ISingletonService : IGuidService { } public class GuidServiceBase : IGuidService { private readonly Guid _item; public GuidServiceBase() { _item = Guid.NewGuid(); } public Guid Id() { return _item; } } public class TransientService : GuidServiceBase, ITransientService { } public class ScopedService : GuidServiceBase, IScopedService { } public class SingletonService : GuidServiceBase, ISingletonService { }}
然後用VS2017建立一個Mvc項目,在Startup類中註冊這三個服務
public void ConfigureServices(IServiceCollection services) { services.AddTransient<ITransientService, TransientService>(); services.AddScoped<IScopedService, ScopedService>(); services.AddSingleton<ISingletonService, SingletonService>(); services.AddMvc(); }
既然註冊了,在Controller中就可以使用這些服務了,我們採取建構函式注入的方式,來給Controller注入這些服務外掛程式
using Microsoft.AspNetCore.Mvc;namespace LifetimeOfDI.Controllers{ public class HomeController : Controller { private readonly ITransientService _guidTransientService; private readonly IScopedService _guidScopedService; private readonly ISingletonService _guidSingletonService; // 建構函式注入 public HomeController(ITransientService guidTransientService, IScopedService guidScopedService, ISingletonService guidSingletonService) { _guidTransientService = guidTransientService; _guidScopedService = guidScopedService; _guidSingletonService = guidSingletonService; } public IActionResult Index() { // 傳GUID給頁面 ViewBag.TransientItem = _guidTransientService.Id(); ViewBag.ScopedItem = _guidScopedService.Id(); ViewBag.SingletonItem = _guidSingletonService.Id(); return View(); } }}
在Index.cshtml頁面中顯示這三個GUID
@{ ViewData["Title"] = "Home Page";}<div class="row"> <div> <h2>Guid Service Shows</h2> <h3>TransientGuid: @ViewBag.TransientItem</h3> <h3>ScopedGuid: @ViewBag.ScopedItem</h3> <h3>SingletonGuid: @ViewBag.SingletonItem</h3> </div></div>
我們啟動兩個瀏覽器,可以看出單例模式的Guid在兩個瀏覽器這種是一致的,而且,並且重新整理瀏覽器,也不會改變;另外兩個因為每次重新整理都發起了一次新的請求,所以Guid都不同。
三、使用局部頁面技術驗證範圍生命週期的特點
上一節沒能驗證Scoped類型生命週期,因為每次重新整理都發起了一次新的請求。我們需要驗證一個Web請求,對服務的多次使用。如何驗證呢?這裡我們藉助局部頁面技術。
建立一個局部頁面IndexPartial.cshtml,在局部頁面中引用我們的自訂服務命名空間,並注入三個服務,分別顯示其Id。
@*引用自訂介面的命名空間*@@using LifetimeOfDI@*依賴注入*@@inject ITransientService TransientService@inject IScopedService ScopedService@inject ISingletonService SingletonService@*輸出服務提供的Id*@<div class="row"> <div> <h2>Guid Service Shows</h2> <h3>TransientGuid: @TransientService.Id()</h3> <h3>ScopedGuid: @ScopedService.Id()</h3> <h3>SingletonGuid: @SingletonService.Id()</h3> </div></div>
在Index.cshtml頁面中兩次引用這個局部頁,這樣就可以展示,一次請求兩次調用服務介面的情境。
@{ ViewData["Title"] = "Home Page";}@Html.Partial("IndexPartial")@Html.Partial("IndexPartial")
看看效果吧
從效果看,範圍生命週期內的Id在一次請求的多次調用中保持了一致性;而瞬態聲明周期的則每次調用都不同;單例聲明周期的則不用說了,不同請求的多次調用都不變,更不用說相同請求了。
至此,我們理解了三種生命週期的的特點,在業務開發中可以按需使用了。
07、NetCore2.0外掛程式架構之生命週期