1. 程式人生 > >07、NetCore2.0插件框架之生命周期

07、NetCore2.0插件框架之生命周期

系統 star 源碼 p s partial text strong cti exp

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; 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插件框架之生命周期