简体   繁体   English

.Net Core DI - 通过构造函数注入与使用 scope 解析

[英].Net Core DI - inject via constructor vs resolve using scope

Recently I have started using Worker Services and DI in .NET Core and I am confused about the difference between injecting a service via constructor vs by using scopes.最近我开始在 .NET Core 中使用 Worker Services 和 DI,我对通过构造函数注入服务与使用范围注入服务之间的区别感到困惑。

I have port forwarding software that creates a number of port forwardings as requested by user by creating many PortForwarding class instances.我有端口转发软件,它通过创建许多 PortForwarding class 实例来根据用户的请求创建多个端口转发。

My code - just the lines related to the question:我的代码 - 只是与问题相关的行:

This is how I register the service:这是我注册服务的方式:

static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseSerilog()
            .ConfigureServices((hostContext, services) =>
            {
                services.AddLogging();
                services.AddScoped<ISocket, TheSocket>();     //TheSocket creates System.Net.Sockets.Socket
                services.AddScoped<IPortForwarding, PortForwarding>();
            
               <more implementation>
            });

Then in PortForwarding object I need an instance of TheSocket: ISocket, which I can create in two ways:然后在 PortForwarding object 中我需要一个 TheSocket: ISocket 的实例,我可以通过两种方式创建它:

  1. By creating a scope and requesting the ISocket:通过创建 scope 并请求 ISocket:

     public Socket Socket {get; set;} private readonly ILogger<PortForwarding> logger; private readonly IServiceScopeFactory serviceScopeFactory; public PortForwarding(ILogger<PortForwarding> logger, IServiceScopeFactory serviceScopeFactory) { this.logger = logger; this.serviceScopeFactory = serviceScopeFactory; using IServiceScope scope = serviceScopeFactory.CreateScope(); var socket = scope.ServiceProvider.GetRequiredService<ISocket>(); Socket = socket.Socket; }
  2. With constructor injection:使用构造函数注入:

     public Socket Socket {get; set;} private readonly ILogger<PortForwarding> logger; public PortForwarding(ILogger<PortForwarding> logger, ISocket iSocket) { this.logger = logger; Socket = iSocket.Socket; }

Then I make use of the Socket and the application works fine in both cases.然后我使用套接字,应用程序在这两种情况下都能正常工作。

I have read Microsoft Docs about DI but since both versions work the same way - at least during my tests - I am not sure which one to use and why.我已阅读有关 DI 的Microsoft 文档,但由于两个版本的工作方式相同 - 至少在我的测试期间 - 我不确定使用哪一个以及为什么。

The only difference I can see is that with constructor injection I create one instance of the Socket and by using IServiceScopeFactory, I could request more instances - am I right, and is this the only difference between those two methods of DI?我能看到的唯一区别是,通过构造函数注入,我创建了一个 Socket 实例,而通过使用 IServiceScopeFactory,我可以请求更多实例——我说得对吗,这是这两种 DI 方法之间的唯一区别吗?

Appreciate any clarifications.感谢任何澄清。

The first method actually creates a sub container, and then you get service instances from the sub container.第一种方法实际上创建了一个子容器,然后你从子容器中获取服务实例。

Generally, it is recommended to inject from the construction method.一般推荐从构造方法注入。 The reason is that if you create a sub container, the objects created from the sub container will be destroyed when the sub container is recycled, which means that you need to manage the life cycle of the sub container and its creation service by yourself原因是如果你创建了一个子容器,从子容器创建的对象在子容器被回收时会被销毁,这意味着你需要自己管理子容器的生命周期和它的创建服务

You should go with the constructor injection.您应该使用构造函数注入 go 。

The first approach looks like you are using some parts of DI internals instead of actually letting DI container do its job and it ends up looking like a "ServiceLocator" which is by now considered widely as an anti-pattern.第一种方法看起来您正在使用 DI 内部的某些部分,而不是真正让 DI 容器完成它的工作,它最终看起来像一个“ServiceLocator”,现在被广泛认为是一种反模式。 If you try to have this covered by unit tests you will find yourself making mocks of interfaces totally unrelated to job the class is supposed to fulfill.如果您尝试让单元测试涵盖这一点,您会发现自己在模拟与 class 应该完成的工作完全无关的接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM