.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吗?有影响吗?
答案 0 :(得分:0)
Schoooo Wheeeeee。
好像您遇到了一场小型圣战。
这里是链接和讨论:
https://github.com/dotnet/extensions/issues/553
“ AddHostedService不应为单例。请不要这样做 重大变革”,
“此线程非常奇怪。HostedServices应该为单例 不是短暂的。”
这似乎是您的情况下的主要评论:
“因为它是我们期望的最常见方案的帮助者。 如果那不适合您,则直接使用DI方法。“
上一个响应:
根据此示例:
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
}
}
另一个链接:
最终,我认为这是问题所在