Search code examples
c#asp.net-coredependency-injectionasp.net-core-hosted-services

.net core dependency injection to hosted service


My .net core app needs to crawl data in a specified time interval. I have chosen to implement IHostedService to run it in parallel with API. The hosted service needs some services injected. I register them in startup.cs, but I get an error:

System.InvalidOperationException: 'Cannot consume scoped service 'IXService' from singleton 'Microsoft.AspNetCore.Hosting.Internal.HostedServiceExecutor'.'

My startup.cs:

services.AddScoped<IXService, XService>();
services.AddHostedService<MyHostedService>();

I had a similar problem yet with DbContext, I solved it with https://stackoverflow.com/a/48368934/8475133, but this time I need dependency injection going through deeper layers and dealing with IServiceScopeFactory in each doesn't seem to be an elegant solution.


Solution

  • The reason you're not allowed to do this is because MyHostedService has a singleton lifetime, which is a longer lifetime than scoped. The basic assumption here is that a service that is registered as scoped should not be kept alive indefinitely, this could easily happen if a singleton service keeps a reference to a scoped service.

    I think the solution you're looking for is to inject IServiceProvider into MyHostedService, use it to create a new scope and new XService instance whenever you need it.

    That is, replace

    _xService.Foo();
    

    with

    using(var scope = _serviceProvider.CreateScope()) {
        var xService = scope.ServiceProvider.GetService<IXService>();
        xService.Foo();
    }
    

    An alternative, of course, would be to simply register XService as a singleton, by just replacing the call to AddScoped with AddSingleton, but I would not recommend it.

    Edit: I must admit to not reading your link before posting my response. However, I still think this is the most elegant solution.