asp.net core 系列 4 注入服务的生存期
一.服务的生存期
在容器中每个注册的服务,根据程序应用需求都可以选择合适的服务生存期,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 系列 4 注入服务的生存期的更多相关文章
- asp.net core系列 74 Exceptionless服务端安装
一. Docker安装 Docker 要求版本Docker 18.09.0+以上 安装地址:https://www.runoob.com/docker/windows-docker-insta ...
- asp.net core 系列 17 通用主机 IHostBuilder
一.概述 ASP.NET Core 通用主机 (HostBuilder),该主机对于托管不处理 HTTP 请求的应用非常有用.通用主机的目标是将 HTTP 管道从 Web 主机 API 中分离出来,从 ...
- 【目录】asp.net core系列篇
随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...
- asp.net core 系列 3 依赖注入服务
一. 依赖注入概述 在软件设计的通用原则中,SOLID是非常流行的缩略语,它由5个设计原则的首字母构成:单一原则(S).开放封闭原则(O).里氏替换原则(L).接口分离原则(I).依赖反转原则(D). ...
- asp.net core 系列之Dependency injection(依赖注入)
这篇文章主要讲解asp.net core 依赖注入的一些内容. ASP.NET Core支持依赖注入.这是一种在类和其依赖之间实现控制反转的一种技术(IOC). 一.依赖注入概述 1.原始的代码 依赖 ...
- Asp.net Core 系列之--3.领域、仓储、服务简单实现
ChuanGoing 2019-11-11 距离上篇近两个月时间,一方面时因为其他事情耽搁,另一方面也是之前准备不足,关于领域驱动有几个地方没有想通透,也就没有继续码字.目前网络包括园子里大多领域驱 ...
- 在 ASP.NET Core 中执行租户服务
在 ASP.NET Core 中执行租户服务 不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: http://gunna ...
- ASP.NET Core 2.0 : 五.服务是如何加载并运行的, Kestrel、配置与环境
"跨平台"后的ASP.Net Core是如何接收并处理请求的呢? 它的运行和处理机制和之前有什么不同? 本章从"宏观"到"微观"地看一下它的 ...
- asp.net core系列 40 Web 应用MVC 介绍与详细示例
一. MVC介绍 MVC架构模式有助于实现关注点分离.视图和控制器均依赖于模型. 但是,模型既不依赖于视图,也不依赖于控制器. 这是分离的一个关键优势. 这种分离允许模型独立于可视化展示进行构建和测试 ...
随机推荐
- 服务器、IP地址和域名之间有什么关系?
一.服务器 服务器其实就像我们的家用电脑一样,也有主板.CPU.内存.硬盘.电源等,但是由于它们处理问题的不同,服务器更像一台加强的家用电脑,服务器是为展网络业务而存放.处理数据的,所以服务器一般是存 ...
- XFire+Spring构建Web Service经验总结
使用工具 MyEclipse:6.5 ,tomcat6.x. 1.新建web项目,要导入用的包: 2程序结构: 3 web.xml配置文件 <?xml version="1.0&quo ...
- Set接口下的集合
一.集合(定义字段的时候统一使用包装类) 1.集合大类分为List.Set.Map三种,其中,List集合是有序可重复的,并且可以使用普通for循环.增强for循环.正向迭代器.双向迭代器:Set集合 ...
- 【ABP.Net】1.创建项目&介绍框架结构
既然已经打开这个页面了,我就不介绍什么是ABP了.哈哈哈,如果想知道,请移驾.反正我是不说. 1.首先打开https://aspnetboilerplate.com/Templates 下载所需要的A ...
- ABC113 AK失败记
众所周知, ABC是一场水题盛宴, 也是一场AK盛宴. 但是我却没能AK. 原因也十分可笑: 我在一开始觉得题目太简单, 颓废了.直到我看了第4题之后才找到状态并A了此题...最后时间来不及第三题最后 ...
- vs中 VMDebugger未能加载导致异常
,纠结了许久的一个问题,终于找到了解决 vs中 VMDebugger未能加载导致异常 错误号:80004005 搜了好多,没有一个给出完美的答案. 解决办法:工具->导入和导出设置,重置一下 ...
- 性能之ab简单使用
ab是apache自带的性能测试工具,他所有关注的请求返回的状态码(2XX),不关心后续处理过程,所以测试时间很小,严重依赖CPU颗粒数 一.进入ab存放的目录执行./ab.其中/ab [option ...
- DOM-节点概念-属性
1.节点的概念 页面中的所有内容,包括标签,属性,文本(文字,空格,回车,换行等),也就是说页面的所有内容都可以叫做节点. 2.节点相关的属性 2.1.节点分类 **标签节点:**比如 div 标签, ...
- Linux shell编程 -test
test 命令的格式非常简单 test condition condition 是test命令要测试的一系列参数和值.当用在if-then 语句中时,test 命令看起来是这样的 if test co ...
- centos7防火墙配置
一.在工作中远程连接经常通过堡垒机连接,不能直接开启防火墙.所以就需要写入配置文件中 编译配置文件 /etc/firewalld/zones/public.xml <?xml version ...