C# 从托管服务内调用IServiceProvider.CreateScope是否为反模式?

C# 从托管服务内调用IServiceProvider.CreateScope是否为反模式?,c#,dependency-injection,service-locator,C#,Dependency Injection,Service Locator,最近我一直在研究StackOverflow问题 这里有一个答案,建议阅读微软的,尤其是在后台任务中使用范围服务的段落 在该页面中,我们有以下代码的一部分: internal class ConsumeScopedServiceHostedService : IHostedService { ... private void DoWork() { _logger.LogInformation( "Consume Scoped

最近我一直在研究StackOverflow问题

这里有一个答案,建议阅读微软的,尤其是在后台任务中使用范围服务的段落

在该页面中,我们有以下代码的一部分:

internal class ConsumeScopedServiceHostedService : IHostedService
{
    ...
    private void DoWork()
    {
        _logger.LogInformation(
            "Consume Scoped Service Hosted Service is working.");

        using (var scope = Services.CreateScope())
        {
            var scopedProcessingService = 
                scope.ServiceProvider
                    .GetRequiredService<IScopedProcessingService>();

            scopedProcessingService.DoWork();
        }
    }
    ...    
}
内部类ConsumeScopedService HostedService:IHostedService
{
...
私房
{
_logger.login信息(
“使用作用域服务托管服务正在工作。”);
使用(var scope=Services.CreateScope())
{
var scopedProcessingService=
scope.ServiceProvider
.GetRequiredService();
scopedProcessingService.DoWork();
}
}
...    
}

这不是一种反模式吗?在方法内创建作用域并从服务提供程序解析服务?这似乎有一种服务定位器(如果我错了,请纠正我)。

是的,但构造函数注入之外的任何DI容器使用实际上都是服务定位器的使用。在这种情况下没有问题,因为您需要手动获取范围化的实现。出于安全原因,IHostedService不实施作用域注入。只有单例。我可能大错特错,但上次我需要一个如上所述的对象实例时,我使用了一个工厂方法,在该方法中,我调用了Activator
CreateInstance
传递
ServiceProvider
ActivatorUtilities.CreateInstance(\U ServiceProvider)
。这对我来说似乎更为正确(意味着我让工厂在我的实现之外创建实例)。这打破了坚实的D依赖倒置原则。您需要避免自定义对象实例化。您需要将对象创建委托给DI容器。更好的解决方案是使用问题中所示的Microsoft示例。当DI容器在问题的上下文之外使用时,它被认为是最佳解决方案。当
ConsumesScopedServiceHostedService
是合成根目录的一部分时,这很好,并且不被视为反模式。