0七、NetCore2.0依賴注入(DI)之生命週期html
NetCore2.0依賴注入框架(DI)是如何管理注入對象的生命週期的?生命週期有哪幾類,又是在哪些場景下應用的呢?git
------------------------------------------------------------------------------------------------------------github
寫在前面:這是一個系列的文章,總目錄請移步:NetCore2.0技術文章目錄瀏覽器
------------------------------------------------------------------------------------------------------------框架
1、生命週期的分類函數
來看看系統依賴注入框架(DI)的開源代碼:ui
namespace Microsoft.Extensions.DependencyInjection
{
public enum ServiceLifetime
{
Singleton,
Scoped,
Transient
}
}
從源碼能夠看出,依賴注入框架(DI)支持三種生命週期管理模式spa
單例模式,服務在第一次請求時被建立,其後的每次請求都沿用這個已建立的服務。咱們不用再本身寫單例了。code
做用域模式,服務在每次請求時被建立,整個請求過程當中都貫穿使用這個建立的服務。好比Web頁面的一次請求。htm
瞬態模式,服務在每次請求時被建立,它最好被用於輕量級無狀態服務。
2、重現三種生命週期的應用場景
首先咱們建立三個服務,用來提供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都不一樣。
3、使用局部頁面技術驗證做用域生命週期的特色
上一節沒能驗證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在一次請求的屢次調用中保持了一致性;而瞬態生命週期則每次調用都不一樣;單例生命週期則不用說了,不一樣請求的屢次調用都不變,更不用說相同請求了。
至此,咱們理解了三種生命週期的的特色,在業務開發中能夠按需使用了。