• 07、NetCore2.0依赖注入(DI)之生命周期


    07、NetCore2.0依赖注入(DI)之生命周期

    NetCore2.0依赖注入框架(DI)是如何管理注入对象的生命周期的?生命周期有哪几类,又是在哪些场景下应用的呢?

    ------------------------------------------------------------------------------------------------------------

     写在前面:这是一个系列的文章,总目录请移步: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在一次请求的多次调用中保持了一致性;而瞬态生命周期则每次调用都不同;单例生命周期则不用说了,不同请求的多次调用都不变,更不用说相同请求了。

    至此,我们理解了三种生命周期的的特点,在业务开发中可以按需使用了。  

    【敦格原创】欢迎引用,请注明来源:http://www.cnblogs.com/netcore2
  • 相关阅读:
    目录或文件被损坏且无法读取怎么办
    mvn前端node版本工具操作手册
    经典算法思想1——动态规划( Dynamic Programming)
    二叉树的遍历
    2.1最长递增子序列动态规划解法
    二叉树遍历分析(后缀算法的灵魂)
    记一次hive提交spark任务报错
    Ue4 CharacterMovementComponent 角色移动组件
    Ue4 TArray的属性同步
    Python 特殊语法 filter、map、reduce、lambda、yield
  • 原文地址:https://www.cnblogs.com/netcore2/p/7419045.html
Copyright © 2020-2023  润新知