07、NetCore2.0插件框架之生命周期
07、NetCore2.0插件框架之生命周期
NetCore2.0插件框架是如何管理插件的生命周期的?生命周期有哪幾類,又是在哪些場景下應用的呢?
一、生命周期的分類
我們可以查看系統DI(依賴倒置)的開源代碼:
namespace Microsoft.Extensions.DependencyInjection
{
public enum ServiceLifetime
{
Singleton,
Scoped,
Transient
}
}
從源碼可以看出,DI框架支持三種生命周期管理模式
- Singleton
單例模式
- Scoped
作用域模式,服務在每次請求時被創建,整個請求過程中都貫穿使用這個創建的服務。比如Web頁面的一次請求。
- Transient
瞬態模式,服務在每次請求時被創建,它最好被用於輕量級無狀態服務。
二、重現三種生命周期的應用場景
首先我們創建三個服務,用來提供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; publicGuidServiceBase() { _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插件框架之生命周期