0七、NetCore2.0依賴注入(DI)之生命週期

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

  • Singleton

         單例模式,服務在第一次請求時被建立,其後的每次請求都沿用這個已建立的服務。咱們不用再本身寫單例了。code

  • Scoped

     做用域模式,服務在每次請求時被建立,整個請求過程當中都貫穿使用這個建立的服務。好比Web頁面的一次請求。htm

  • Transient

   瞬態模式,服務在每次請求時被建立,它最好被用於輕量級無狀態服務。

 

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在一次請求的屢次調用中保持了一致性;而瞬態生命週期則每次調用都不一樣;單例生命週期則不用說了,不一樣請求的屢次調用都不變,更不用說相同請求了。

至此,咱們理解了三種生命週期的的特色,在業務開發中能夠按需使用了。  

相關文章
相關標籤/搜索