引言
我印象中记得如果在ASP.NET Core中使用内置的依赖注入,并且后台任务模式下有些情况使用构造函数注入会报错,但是我忘了是什么错误什么原因。然后我在网上找了一句话叫做
使用ASP.NET Core,您可以选择创建和管理自己的范围,通过调用CreateScope()来获取HttpRequest之外的服务。
但是本文不讨论这个东西,我今天突然好奇IServiceScopeFactory和IServiceProvider都可以创建CreateScope,具体有什么区别那?下面来简单看看。.
操作
本文示例环境:vs2022、.Net6
CreateScope将创建一个完全独立于任何当前作用域的新作用域。如果从新作用域解析服务,它将返回该服务的新实例。
IServiceScopeFactory
public class OperationLogHandler : INotificationHandler<AddOperationLogEvent>
{
private readonly IServiceScopeFactory _serviceScopeFactory;
public OperationLogHandler(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public async Task Handle(AddOperationLogEvent notification, CancellationToken cancellationToken)
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var _httpContextAccessor = scope.ServiceProvider.GetRequiredService<IHttpContextAccessor>();
var _operationLogRepository = scope.ServiceProvider.GetRequiredService<IOperationLogRepository>();
if (notification is null || !notification.IsValidOperation())
return;
//xxx
}
}
}
IServiceScopeFactory的CreateScope方法实现是ServiceProviderEngineScope下面的
public IServiceScope CreateScope() => this.RootProvider.CreateScope();
CreateScope方法实现是
internal IServiceScope CreateScope()
{
if (this._disposed)
ThrowHelper.ThrowObjectDisposedException();
return (IServiceScope) new ServiceProviderEngineScope(this, false);
}
IServiceProvider
public class OperationLogHandler : INotificationHandler<AddOperationLogEvent>
{
private readonly IServiceProvider _serviceProvider;
public OperationLogHandler(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task Handle(AddOperationLogEvent notification, CancellationToken cancellationToken)
{
using (var scope = _serviceProvider.CreateScope())
{
var _httpContextAccessor = scope.ServiceProvider.GetRequiredService<IHttpContextAccessor>();
var _operationLogRepository = scope.ServiceProvider.GetRequiredService<IOperationLogRepository>();
if (notification is null || !notification.IsValidOperation())
return;
//xxx
}
}
}
IServiceProvider的CreateScope方法实现是
public static IServiceScope CreateScope(this IServiceProvider provider) => provider.GetRequiredService<IServiceScopeFactory>().CreateScope();
最后调用的实现类也是ServiceProviderEngineScope里面的CreateScope方法
public IServiceScope CreateScope() => this.RootProvider.CreateScope();
结论
因为IServiceScopeFactory和IServiceProvider最后调用的都是ServiceProviderEngineScope里面的CreateScope方法,所以我认为它俩是一样的。
资料
ServiceProviderEngineScope实现类在Microsoft.AspNetCore.App\6.0.5\Microsoft.Extensions.DependencyInjection.dll下面的Microsoft.Extensions.DependencyInjection.ServiceLookup文件夹下。