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在一次请求的屡次调用中保持了一致性;而瞬态生命周期则每次调用都不一样;单例生命周期则不用说了,不一样请求的屡次调用都不变,更不用说相同请求了。
至此,咱们理解了三种生命周期的的特色,在业务开发中能够按需使用了。