ServiceScopeFactory的使用方式
上篇文章谈到在项目中遇到了一个问题,其实就是生命周期的问题,在构造函数的参数中使用了scope生命周期的服务,然后使用ServiceScopeFactory去解决这一问题 ,但是使用方式好像不太正确
上篇文章说遇到了问题,ServiceScopeFactory使用方式好像不太正确,为什么?因为构造这个管道的原计划是针对于每一个请求,但是现在好像变成了单例,代码如下:
public class MyMiddleware
{
private readonly RequestDelegate _next;
private readonly IServiceScopeFactory _scopeFactory;
private readonly IServiceScope serviceScope;
private readonly IMyService _service;
public MyMiddleware(RequestDelegate next, IServiceScopeFactory scopeFactory)
{
_next = next;
_scopeFactory = scopeFactory;
serviceScope = _scopeFactory.CreateScope();
_service = serviceScope.ServiceProvider.GetRequiredService<IMyService>()
}
public async Task InvokeAsync(HttpContext httpContext)
{
// 在这里使用 myService 做一些事情
myService.Handle(httpContext);
// 调用下一个中间件
await _next(httpContext);
// 注意:一旦离开 using 块,服务范围将被释放,并且所有通过该范围解析的服务也将被释放
}
}
如上所示代码,虽然也能跑,但是却搞不好就会有并发问题,因为所有的请求都是用的同一个_service,而我们本意是针对于每个httpcontext,都获取一个服务。但是也能跑 :)
而实际上我们想写的是如下的代码:
public class MyMiddleware
{
private readonly RequestDelegate _next;
private readonly IServiceScopeFactory _scopeFactory;
public MyMiddleware(RequestDelegate next, IServiceScopeFactory scopeFactory)
{
_next = next;
_scopeFactory = scopeFactory;
}
public async Task InvokeAsync(HttpContext httpContext)
{
// 创建一个新的服务范围
using (var scope = _scopeFactory.CreateScope())
{
// 从服务范围中解析你需要的服务
var myService = scope.ServiceProvider.GetRequiredService<IMyService>();
// 在这里使用 myService 做一些事情
// 调用下一个中间件
await _next(httpContext);
}
// 注意:一旦离开 using 块,服务范围将被释放,并且所有通过该范围解析的服务也将被释放
}
}
这意味着服务的实例是在每个请求的基础上创建的。这在处理依赖关系注入(DI)时特别有用,当你希望为每个请求创建新的服务实例时。
总结
两种方式都不能算错,主要是看用在什么情况下,如果业务较为复杂,有并发问题,当然还是下面的写法为好。
这里主要是记录一下当时脑抽写的代码。
分类:
Asp.net Core
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· 深度对比:PostgreSQL 和 SQL Server 在统计信息维护中的关键差异