简体   繁体   中英

.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.

I have port forwarding software that creates a number of port forwardings as requested by user by creating many PortForwarding class instances.

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:

  1. By creating a scope and requesting the 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.

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?

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.

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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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