.Net Core 3.1-IHosted服务(AddHostedService <T>)无法解析依赖项注册

时间:2020-07-28 19:30:14

标签: dependency-injection background-service .net-core-3.1 ihostedservice

.net核心中有一个API项目,.net核心中有一个库项目,我们在其中定义了后台进程(使用IHosted Service的后台服务)。

在API项目中,我们将后台服务的依赖项注册为:

services.AddHostedService<MyBackgroundProcess>();

,我们还有其他一些范围,瞬态和单例依赖项,例如:

services.AddScoped<IHttpClientService , HttpClientService>();
services.AddScoped<IUserService, UserService>();
services.AddTransient<IMyTransientService, MyTransientService>();
services.AddScoped<IMyScopeService, MyScopeService>();

在我们的后台服务项目的构造函数中,我们注入一些作用域和临时依赖项,例如:

public MyBackgroundProcess(IHttpClientService iHttpClientService, IUserService iUserService, IMyTransientService iMyTransientServcie, IMyScopeService iMyScopeService)                                                      
        {
            _iHttpClientService = iHttpClientService;
            _iUserService = iUserService;
            _iMyTransientServcie = iMyTransientServcie;
            _iMyScopeService = iMyScopeService;
        }

我能够解决.net core 2.2中的这些作用域依赖性。我从我的API项目中获得了所有这些值。当我从API项目调用后台服务时,将调用后台进程构造函数。所以我正在获取所有更新的依赖项。

当我将项目迁移到.net core 3.1时出现了问题。现在我的依赖项为空。这些未与我从中调用这些后台服务的API项目同步。我们正在使用.net core inbuild DI。将应用程序部署到服务结构时将调用IHostedService / Background服务的构造函数,在从API调用后台进程时不会调用它。

我的API业务逻辑构造函数如下:

public MyAPIManager(IMyTransientService myTransientService, IMyScopeService myScopedService, IHostedService myBackGroundProcess1,
                                 IHostedService myBackgroundProcess2, IServiceProvider serviceProvider)
        {
            _myTransientService = myTransientService;
            _myScopedService = myScopedService;
            _myBackGroundService1 = myBackGroundService1 as MyBackgroundServiceA;
            _myBackGroundService2 = myBackGroundService2 as MyBackgroundServiceB;
            if (_myBackGroundService2 == null)
            {
                var services = serviceProvider.GetServices<IHostedService>();
                _myBackGroundService2 = services.First(o => o.GetType() == typeof(MyBackgroundServiceB)) as MyBackgroundServiceB;
            }
        }

在这里,我正在注入,作用域和瞬态依赖项以及2个后台服务。每当我从.net core 2.2中的“ serviceProvider.GetServices()”获取IHostedService的实例时,它都会调用我的DI中注册的所有IHosted服务的构造函数,但在.net core 3.1中,它将调用不调用后台服务的构造函数。


更新-

我尝试将我的后台服务注册为 Transient ,而不是 AddHostedService ,如下所示:

services.AddTransient<IHostedService, MyBackgroundService1>();
 services.AddTransient<IHostedService, MyBackgroundService2>();

似乎它现在正在运行,每次我尝试解析类型时都会调用构造函数:

var services = serviceProvider.GetServices<IHostedService>();
                _myBackgroundProcess1 = services.First(o => o.GetType() == typeof(MyBackgroundProcessA)) as MyBackgroundProcessA;

建议像这样注册IHostedService吗?有影响吗?

1 个答案:

答案 0 :(得分:0)

Schoooo Wheeeeee。

好像您遇到了一场小型圣战。

这里是链接和讨论:

https://github.com/dotnet/extensions/issues/553

“ AddHostedService不应为单例。请不要这样做 重大变革”,

“此线程非常奇怪。HostedServices应该为单例 不是短暂的。”

这似乎是您的情况下的主要评论:

“因为它是我们期望的最常见方案的帮助者。 如果那不适合您,则直接使用DI方法。“

上一个响应:

根据此示例:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio#consuming-a-scoped-service-in-a-background-task

services.AddHostedService<ConsumeScopedServiceHostedService>();
services.AddScoped<IScopedProcessingService, ScopedProcessingService>();

(上面示例中的代码)

您必须注册依赖项

services.AddHostedService<MyBackgroundProcess>();

services.AddScoped<IHttpClientService , MyConcreteHttpClientService>();
services.AddScoped<IUserService, MyConcreteUserService>();
services.AddScoped<IMyTransientService, MyConcreteMyTransientService>();
services.AddScoped<IMyScopeService, MyConcreteScopeService>();

如果您不使用某种“自动扫描”解决方案,那么这个(上面)当然是...。 (也许您的2.2代码中有自动扫描解决方案吗?)

类似

NetCore.AutoRegisterDi

https://www.thereformedprogrammer.net/asp-net-core-fast-and-automatic-dependency-injection-setup/

public static class NetCoreDiSetupExtensions
{
    public static void RegisterServiceLayerDi
        (this IServiceCollection services)
    {
        services.RegisterAssemblyPublicNonGenericClasses()
            .AsPublicImplementedInterfaces();
 
        //put any non-standard DI registration, e.g. generic types, here
    }
}

另一个链接:

最终,我认为这是问题所在

https://github.com/aspnet/Hosting/blob/master/src/Microsoft.Extensions.Hosting.Abstractions/ServiceCollectionHostedServiceExtensions.cs#L18