一.服务的生存期

  在容器中每个注册的服务,根据程序应用需求都可以选择合适的服务生存期,ASP.NET Core 服务有三种生存期配置:

    (1) Transient:暂时生存期,在每次请求时被创建。 这种生存期适合轻量级的,无状态的服务。

    (2) Scoped: 作用域生存期,在每次请求被创建一次。

    (3) Singleton: 单例生存期,在它们第一次被请求时创建。每个后续请求将使用相同的实例。如果应用程序需要单例行为,建议让服务容器管理服务的生命周期,而不是在自己的类中实现单例模式。

  1.1 演示案例

    为了演示生存期和注册选项之间的差异, 以下服务接口,任务是演示标识符 OperationId 的操作值变化。 根据为以下接口配置操作服务的生存期的方式,容器在类请求时提供相同或不同的服务实例:

   public interface IOperation
{
Guid OperationId { get; }
}
//用于演示暂时生存期
public interface IOperationTransient : IOperation
{
}
//用于演示作用域生存期
public interface IOperationScoped : IOperation
{
}
//用于演示单例生存期
public interface IOperationSingleton : IOperation
{
}
//用于演示单例中空GUID
public interface IOperationSingletonInstance : IOperation
{
}

    上面四种服务接口在 Operation 类中实现。 调用 Operation类时将自动生成一个 GUID(如果实例化Operation类时没有指定GUID),下面是Operation类的实现:

 public class Operation : IOperationTransient,
IOperationScoped,
IOperationSingleton,
IOperationSingletonInstance
{
/// <summary>
/// 构造方法中生成GUID,在实例化类时
/// </summary>
public Operation() : this(Guid.NewGuid())
{
} public Operation(Guid id)
{
OperationId = id;
} /// <summary>
/// 获取GUID
/// </summary>
public Guid OperationId { get; private set; }
}

    再注册一个 OperationService 服务,该服务取决于每个其他 Operation 类型。 当通过依赖关系注入请求 OperationService 时,它将接收每个服务的新实例或基于从属服务(Operation )的生存期的现有实例。OperationService 服务作用就是第二次调用 Operation类,查看Operation类实例的作用域变化。

    public class OperationService
{ public IOperationTransient TransientOperation { get; }
public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance SingletonInstanceOperation { get; } public OperationService(
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance instanceOperation)
{
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation = instanceOperation;
}
}

    (1) 如果在请求时创建了临时服务(Transient),则 IOperationTransient 服务的 OperationId 与 OperationService 的 OperationId 不同。 OperationService 将接收 IOperationTransient 类的新实例。 新实例将生成一个不同的 OperationId。

    (2) 如果按请求创建有作用域的服务(Scoped),则 IOperationScoped 服务的 OperationId 与请求中 OperationService 的该 ID 相同。 在请求中,两个服务共享不同的 OperationId 值。

    (3) 如果单一实例服务(Singleton),则只创建一次 并在所有请求和所有服务中使用,则 OperationId 在所有服务请求中保持不变。

    下面是在 Startup.ConfigureServices 服务容器中注册,指定服务的生存期:

            services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty)); services.AddTransient<OperationService, OperationService>();

    为了演示各个请求中的对象生存期。 下面示例应用 Index页面,请求 IOperation 类型和 OperationService。 然后查看Operation类属性OperationId 值的变化:

public class IndexModel : PageModel
{
public OperationService OperationService { get; }
public IOperationTransient TransientOperation { get; }
public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance SingletonInstanceOperation { get; } public IndexModel(
OperationService operationService,
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance singletonInstanceOperation)
{
OperationService = operationService;
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation = singletonInstanceOperation;
} public string BindGUIDMsg { get; set; }
public void OnGet()
{
BindGUIDMsg += "IOperation操作: <br/> ";
BindGUIDMsg += "暂时性:" + TransientOperation.OperationId.ToString() + "</br>";
BindGUIDMsg += "有作用域:" + ScopedOperation.OperationId.ToString() + "</br>";
BindGUIDMsg += "单一实例:" + SingletonOperation.OperationId.ToString() + "</br>";
BindGUIDMsg += "实例:" + SingletonInstanceOperation.OperationId.ToString() + "</br>"; BindGUIDMsg += "</br></br></br>OperationService操作:</br>";
BindGUIDMsg += "暂时性:" + OperationService.TransientOperation.OperationId.ToString() + "</br>";
BindGUIDMsg += "有作用域:" + OperationService.ScopedOperation.OperationId.ToString() + "</br>";
BindGUIDMsg += "单一实例:" + OperationService.SingletonOperation.OperationId.ToString() + "</br>";
BindGUIDMsg += "实例:" + OperationService.SingletonInstanceOperation.OperationId.ToString() + "</br>";
}
}
    <div >
@{
@Html.Raw(@Model.BindGUIDMsg);
}
</div>

    第一次Index页面请求:

    IOperation 操作:
    暂时性:8ef874a3-743d-4288-98d4-3df126cd940d 
    有作用域:256ff050-f469-4ea3-8dde-16cdd3087c83 
    单一实例:d2caf297-a9b1-4dcf-ADDA-c68e46fe0741 
    实例:00000000-0000-0000-0000 -000000000000

    OperationService操作:
    暂时性:5411fd0d-f2e1-4885-beee-2d7ccf48dceb 
    有作用域:256ff050-f469-4ea3-8dde-16cdd3087c83 
    单一实例:d2caf297-a9b1-4dcf-adda-c68e46fe0741 
    实例:00000000-0000-0000- 0000-000000000000

    第二次Index页面请求:

    IOperation操作:
    暂时性:e685fd0e-d2e0-4900-9eff-e6bc41cd2f80
    有作用域:ca233b49-8326-4a7e-8ee4-6993d70786ed
    单一实例:d2caf297-a9b1-4dcf-adda-c68e46fe0741
    实例:00000000-0000-0000-0000-000000000000

    OperationService操作:
    暂时性:db89be00-c3b7-4f99-bead-5be693ccc2c0
    有作用域:ca233b49-8326-4a7e-8ee4-6993d70786ed
    单一实例:d2caf297-a9b1-4dcf-adda-c68e46fe0741
    实例:00000000-0000-0000-0000-000000000000

  下面再总结一下:

    (1)暂时性注册的服务,每次调用服务都会是一个新的服务对象实例。相当于在IndexModel类的局部(方法或属性中)实例化一个依赖对象Operation类,伪代码是:

public class IndexModel
{
public void OnGet()
{
//加载index页时,实例化了二次Operation类
         //第一次
OperationService operationService=new OperationService();
         //第二次
         IOperationTransient TransientOperation =new Operation();
}
}

    (2)作用域注册的服务,一次请求内(加载一次index页)对象实例是相同的,但每次请求会产生一个新实例。相当于在IndexModel类的全局中实例化一次依赖对象Operation类,伪代码是:

        OperationService operationService = null;
public IndexModel()
{
operationService = new OperationService();
operationService.ScopedOperation = new Operation();
} public void OnGet()
{
operationService.ScopedOperation.OperationId;
IOperationScoped operationScoped=operationService.ScopedOperation;
operationScoped.OperationId

    (3)单例注册的服务,实例对象对每个对象和每个请求都是相同的。相当于在整个应用Application中只实例化一次,常见的单例模式。

  参考文献:

    官方文档:ASP.NET Core

asp.net core 系列 4 注入服务的生存期的更多相关文章

  1. asp.net core系列 74 Exceptionless服务端安装

    一.   Docker安装 Docker   要求版本Docker 18.09.0+以上 安装地址:https://www.runoob.com/docker/windows-docker-insta ...

  2. asp.net core 系列 17 通用主机 IHostBuilder

    一.概述 ASP.NET Core 通用主机 (HostBuilder),该主机对于托管不处理 HTTP 请求的应用非常有用.通用主机的目标是将 HTTP 管道从 Web 主机 API 中分离出来,从 ...

  3. 【目录】asp.net core系列篇

    随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...

  4. asp.net core 系列 3 依赖注入服务

    一. 依赖注入概述 在软件设计的通用原则中,SOLID是非常流行的缩略语,它由5个设计原则的首字母构成:单一原则(S).开放封闭原则(O).里氏替换原则(L).接口分离原则(I).依赖反转原则(D). ...

  5. asp.net core 系列之Dependency injection(依赖注入)

    这篇文章主要讲解asp.net core 依赖注入的一些内容. ASP.NET Core支持依赖注入.这是一种在类和其依赖之间实现控制反转的一种技术(IOC). 一.依赖注入概述 1.原始的代码 依赖 ...

  6. Asp.net Core 系列之--3.领域、仓储、服务简单实现

    ChuanGoing 2019-11-11  距离上篇近两个月时间,一方面时因为其他事情耽搁,另一方面也是之前准备不足,关于领域驱动有几个地方没有想通透,也就没有继续码字.目前网络包括园子里大多领域驱 ...

  7. 在 ASP.NET Core 中执行租户服务

    在 ASP.NET Core 中执行租户服务 不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: http://gunna ...

  8. ASP.NET Core 2.0 : 五.服务是如何加载并运行的, Kestrel、配置与环境

    "跨平台"后的ASP.Net Core是如何接收并处理请求的呢? 它的运行和处理机制和之前有什么不同? 本章从"宏观"到"微观"地看一下它的 ...

  9. asp.net core系列 40 Web 应用MVC 介绍与详细示例

    一. MVC介绍 MVC架构模式有助于实现关注点分离.视图和控制器均依赖于模型. 但是,模型既不依赖于视图,也不依赖于控制器. 这是分离的一个关键优势. 这种分离允许模型独立于可视化展示进行构建和测试 ...

随机推荐

  1. Clion+Cmake+Qt5+Qwt+msys2+MinGW在Windows下的安装配置使用教程

    摘要: CLion, a cross-platform C/C++ IDE. 本文主要介绍基于Clion作为IDE, MinGW作为编译器,CMake作为项目构建工具,开发基于Qt5.qwt的C++图 ...

  2. Little Sub and Isomorphism Sequences ZOJ - 4089

    ZOJ - 4089 思路:可以反正 最长重构序列必然符合  此模式 x  +  {   }  与  {   }  +  x 那么 题意转化为了  找两个距离最长的相同的数.eeee 先离散化 然后 ...

  3. PBRT笔记(14)——光线传播2:体积渲染

    传输公式 传输方程是控制光线在吸收.发射和散射辐射的介质中的行为的基本方程.它解释了第11章中描述的所有体积散射过程--吸收.发射和内.外散射.并给出了一个描述环境中辐射分布的方程.光传输方程实际上是 ...

  4. KMP性质小结

    跪拜_Blackjack_神犇

  5. Selenium 实现 Web 自动化的原理 (软件测试52讲学习笔记)

    Selenium 1.0 的工作原理 Selenium 1.0,又称Selenium RC ,RC是Remote Control的缩写.Selenium RC利用的原理:JavaScript代码可以方 ...

  6. 异步使用委托delegate --- BeginInvoke和EndInvoke方法

    当我们定义一个委托的时候,一般语言运行时会自动帮委托定义BeginInvoke 和 EndInvoke两个方法,这两个方法的作用是可以异步调用委托. 方法BeginInvoke有两个参数: Async ...

  7. 在Codeblocks下配置GoogleTest单元测试工具

    开发工具 我和我的组员的都是使用的是大一老师推荐的codeblocks,所以,就愉快的决定了工具统一为codeblocks,语言C++. 测试单元 老师推荐的是JUnit和VSTS工具,但同学们从大一 ...

  8. 用挂载,使用NTFS移动硬盘,拷贝iPhone里的照片,拷到MAC

    2. 写权限挂载移动硬盘 1) mount查看 2) diskutil umount /dev/disk2 3) sudo mount_ntfs -o rw,nobrowse /dev/disk2s1 ...

  9. ios日期显示NaN

    ios中js通过getMonth()获取到的日期显示NaN,而在其他地方如pc.安卓都是ok的,这是为什么呢,原来这里有个ios的兼容问题,需要将日期中的“-”替换为“/” var time = ne ...

  10. Java_集合

    定义: 是一种工具,就像是容器,能存储任意数量的具有共同属性的对象. 与数组比较优点: (1)数组定义后长度不可变,集合长度可变: (2)数组只能通过下标访问,且下标类型只能是数字型,而有的集合(ma ...