如何在Asp.Net Core中使用生命周期选项
创始人
2024-11-27 17:01:11
0次

 一、服务的生命周期

在Asp.Net Core中,内置容器负责管理服务的生命周期,从被依赖注入容器创建开始,等我们调用完服务时,到容器释放该服务的所有实力为止,有几种形式表现:

  1、Transient:每次请求服务时,都会创建一个新实例,这种生命周期适合用于轻量级服务(如Repository和ApplicationService服务)。

  2、Scoped:为每个HTTP请求创建一个实例,生命周期将横贯整次请求。

  3、SingleTon:在第一次请求服务时,为该服务创建一个实例,之后每次请求将会使用第一次创建好的服务。

  4、Instance:与SingleTon类似,但在应用程序启动时会将该实例注册到容器中,可以理解为比SingleTon还早存在。

应用程序中相关服务的控制生命周期的方法时通过相应的Add*指定,如下三种,当然还可以通过扩展方法来简化ConfigurationServices方法中所见的代码数量。

services.AddTransient();
services.AddScoped();
services.AddSingleton();

二、代码设计服务生命周期

首先设计一些服务相关的操作接口

public interface IOperation
 {
 Guid GetGuid();
 }

 public interface IOperationTransient: IOperation
 {

 }

 public interface IOperationScoped : IOperation
 {

 }

 public interface IOperationSingleton : IOperation
 {
 
 }

 public interface IOperationInstance : IOperation
 {
 
 }

基础服务接口

其次对这些操作类予以实现并生成相关服务

/// 
 /// 常规服务
 /// 
 public class Operation : IOperation
 {
 private readonly Guid _guid;

 public Operation()
 {
 _guid = Guid.NewGuid();
 }

 public Operation(Guid guid)
 {
 _guid = guid == Guid.Empty ? Guid.NewGuid() : guid;
 }

 public Guid GetGuid()
 {
 return _guid;
 }
 }

 /// 
 /// 瞬时服务
 /// 
 public class OperationTransient : IOperationTransient
 {
 private readonly Guid _guid;

 public OperationTransient()
 {
 _guid = Guid.NewGuid();
 }

 public OperationTransient(Guid guid)
 {
 _guid = guid == Guid.Empty ? Guid.NewGuid() : guid;
 }

 public Guid GetGuid()
 {
 return _guid;
 }
 }

 /// 
 /// 单次请求内服务固定
 /// 
 public class OperationScoped : IOperationScoped
 {
 private readonly Guid _guid;

 public OperationScoped()
 {
 _guid = Guid.NewGuid();
 }

 public OperationScoped(Guid guid)
 {
 _guid = guid == Guid.Empty ? Guid.NewGuid() : guid;
 }

 public Guid GetGuid()
 {
 return _guid;
 }
 }


 /// 
 /// 所有请求内固定服务
 /// 
 public class OperationSingleton : IOperationSingleton
 {
 private readonly Guid _guid;

 public OperationSingleton()
 {
 _guid = Guid.NewGuid();
 }

 public OperationSingleton(Guid guid)
 {
 _guid = guid == Guid.Empty ? Guid.NewGuid() : guid;
 }

 public Guid GetGuid()
 {
 return _guid;
 }
 }

 /// 
 /// 应用程序内固定服务
 /// 
 public class OperationInstance : IOperationInstance
 {
 private readonly Guid _guid;

 public OperationInstance()
 {
 _guid = Guid.NewGuid();
 }

 public OperationInstance(Guid guid)
 {
 _guid = guid == Guid.Empty ? Guid.NewGuid() : guid;
 }

 public Guid GetGuid()
 {
 return _guid;
 }
 }

基础服务具体实现

对基础服务的聚合接口,提供统一服务接口

public interface IOperationService
 {
 /// 
 /// 获取四种形式的Guid码
 /// 
 /// 
 List GetGuidString();
 }

聚合服务接口

对基础服务的聚合实现,将基础服务全部接入进来作为统一服务

/// 
 /// 服务调用
 /// 
 public class OperationService : IOperationService
 {
 public IOperationTransient _transientOperation { get; }
 public IOperationScoped _scopedOperation { get; }
 public IOperationSingleton _singletonOperation { get; }
 public IOperationInstance _instanceOperation { get; }

 public OperationService(IOperationTransient transientOperation,
 IOperationScoped scopedOperation,
 IOperationSingleton singletonOperation,
 IOperationInstance instanceOperation)
 {
 _transientOperation = transientOperation;
 _scopedOperation = scopedOperation;
 _singletonOperation = singletonOperation;
 _instanceOperation = instanceOperation;
 }

 public List GetGuidString()
 {
 return new List()
 {
 $"Transient:"+_transientOperation.GetGuid(),
 $"Scoped:"+_scopedOperation.GetGuid(),
 $"Singleton:" +_singletonOperation.GetGuid(),
 $"Instance:"+_instanceOperation.GetGuid(),
 };
 }
 }

聚合服务的实现

在控制器中进行服务注入

[Route("api/[controller]")]
 [ApiController]
 public class ValuesController : ControllerBase
 {
 private readonly IOperationService _operationService;

 public ValuesController(IOperationService operationService)
 {
 _operationService = operationService;
 }

 [HttpGet]
 [Route(nameof(GetGuidString))]
 public ActionResult GetGuidString()
 {
 return string.Join("\n", _operationService.GetGuidString());
 }
 }

在StartUp中完成服务注入逻辑,这里实现服务注入的方式多种均可。

services.AddTransient();
services.AddScoped();
services.AddSingleton();//应用程序启动时便注入该实例
services.AddSingleton(new OperationInstance(Guid.Empty));
services.AddTransient();

通过访问预期Api地址可以得到不同的四种基础服务的Guid信息,

第一次启动程序(不关闭)发起访问:

如何在Asp.Net Core中使用生命周期选项  

第二次(第一次基础上再次访问)发起访问:

如何在Asp.Net Core中使用生命周期选项  

可以看见,两次访问下,Singleton和Instance是相同的,都是由应用程序启动时和应用服务加载时决定完毕,Singleton在首次进入服务时进行分配,并始终保持不变,而Instance在应用程序启动时,便将实例注入,进入服务也保持着最先的实例,没有重新分配实例。而Transient和Scoped则进行着变化。

关闭程序,重启,第三次发起访问:

如何在Asp.Net Core中使用生命周期选项  

可以见到,Singleton和Instance都发生了变化,也说明了之前在Singleton和Instance处写上的作用。

接下来开始设计Transient和Scoped的不同之处,对于已有代码加上新功能,此次我们只针对Scoped和Transient进行比较。

首先在StartUp中将HttpContextAccessor服务注入,目的是在后期能够针对Scoped获取新的服务实例(尽管两个实例是相同的)。

 services.AddHttpContextAccessor();

接着在聚合服务中增加一个方法,用来针对Transient、Scoped测试。

 /// 
 /// 获取Transient、Scoped的Guid码
 /// 
 /// 
 List GetTransientAndScopedGuidString();

在聚合服务实现中实现该方法并对已有的服务重新获取实例,得到不同实例下的Guid码。

public List GetTransientAndScopedGuidString()
 {
 //var tempTransientService = (IOperationTransient)ServiceLocator.Instance.GetService(typeof(IOperationTransient));

 var tempTransientService = (IOperationTransient)_httpContextAccessor.HttpContext.RequestServices.GetService(typeof(IOperationTransient));
 var tempScopedService = (IOperationScoped)_httpContextAccessor.HttpContext.RequestServices.GetService(typeof(IOperationScoped));

 return new List()
 {
 $"原生Transient请求服务:"+_transientOperation.GetGuid(),
 $"手动Transient请求服务:"+ tempTransientService.GetGuid(),
 $"原生Scoped请求服务:"+_scopedOperation.GetGuid(),
 $"手动Scoped请求服务:"+tempScopedService.GetGuid(),
 };
 }

在控制器部分调用该聚合服务即可,并返回相应的结果,本次我返回的结果:

如何在Asp.Net Core中使用生命周期选项  

ASP.NET 是什么

ASP.NET 是开源,跨平台,高性能,轻量级的 Web 应用构建框架,常用于通过 HTML、CSS、JavaScript 以及服务器脚本来构建网页和网站。

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...