[英]Dependency Injection in ASP.NET Core Worker Service
I'm facing some dependency injection issues in .NET Core Worker Service.我在 .NET Core Worker Service 中遇到了一些依赖注入问题。 Please see the below code in
Program.cs
file.请参阅
Program.cs
文件中的以下代码。
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsof)t", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.File(@"C:\MyApp_Log\Log.txt")
.CreateLogger();
try
{
Log.Information("Starting up the service.");
CreateHostBuilder(args).Build().Run();
return;
}
catch (Exception ex)
{
Log.Fatal(ex, "There was a problem starting the service");
return;
}
finally
{
Log.CloseAndFlush();
}
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddScoped<IMyAppCoreService, MyAppCoreService>();
services.AddDbContext<MyAppCSContext>(options => options.UseSqlServer("Data Source=xx.xxx.xx.xxx;Database=Mydb;User ID = sa;Password=mypassword"));
services.AddHostedService<Worker>();
})
.UseSerilog();
}
And please see below code for Worker.cs
file请参阅下面的
Worker.cs
文件代码
private readonly ILogger<Worker> _logger;
private readonly IMyAppCoreService _CoreService;
public Worker(ILogger<Worker> logger, IMyAppCoreService CoreService)
{
_logger = logger;
_CoreService = CoreService;
}
public override Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("The MyApp_CoreService has been Started...");
return base.StartAsync(cancellationToken);
}
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("The MyApp_CoreService has been stopped...");
return base.StopAsync(cancellationToken);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
_CoreService.CheckAndProcessResult();
await Task.Delay(1000, stoppingToken);
}
}
When I run the above query, I got the below query.当我运行上面的查询时,我得到了下面的查询。
Error while validating the service descriptor验证服务描述符时出错
ServiceType: MyApp.CS.Business.Facade.IMyAppCoreService Lifetime: Scoped ImplementationType: MyApp.CS.Business.Services.MyAppCoreService': Unable to resolve service for type 'MyApp.CS.Data.Facade.ICommonRepository' while attempting to activate 'MyApp.CS.Business.Services.MyAppCoreService'.
ServiceType:MyApp.CS.Business.Facade.IMyAppCoreService Lifetime:Scoped ImplementationType:MyApp.CS.Business.Services.MyAppCoreService':尝试激活“MyApp”时无法解析“MyApp.CS.Data.Facade.ICommonRepository”类型的服务.CS.Business.Services.MyAppCoreService'。
Can you please tell me where I was done wrong?你能告诉我我哪里做错了吗?
EDIT: After i register all the interface with its class.编辑:在我用它的 class 注册所有接口之后。 then i got new error as follows.
然后我得到如下新错误。
Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: MyApp_CoreService.Worker': Cannot consume scoped service 'MyApp.CS.Business.Facade.IMyAppCoreService' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.
验证服务描述符“ServiceType:Microsoft.Extensions.Hosting.IHostedService Lifetime:Singleton ImplementationType:MyApp_CoreService.Worker”时出错:无法使用 Z2ED500A3529637175E675A8791B7C56.E 中的范围服务“MyApp.CS.Business.Facade.IMyAppCoreService”托管服务”。
You injected the Serivce IMyAppCoreService
as Scoped.您将
IMyAppCoreService
作为 Scoped 注入。 Scoped Services can only be resolved by a ScopedServiceProvider
. Scoped Services 只能由
ScopedServiceProvider
。
My first guess is that you didn't mean to - you meant to inject your service as Singleton:我的第一个猜测是您不是故意的-您打算将服务注入为 Singleton:
services.AddSingleton<IMyAppCoreService, MyAppCoreService>();
This however might not work since you are using EF Core which injects its Context-like classes as scoped.但是,这可能不起作用,因为您使用的是 EF Core,它将其 Context-like 类作为作用域注入。 You have two options:
你有两个选择:
services.AddDbContext<YourContext>(opts => { ...config...}, ServiceLifetime.Transient);
Have an IServiceProvider
property called ServiceProvider injected into Worker
instead of your service.将一个名为 ServiceProvider 的
IServiceProvider
属性注入Worker
而不是您的服务。
in ExecuteAsync-Loop:在 ExecuteAsync 循环中:
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
using (var scope = ServiceProvider.CreateScope())
{
scope.ServiceProvider.GetRequiredService<IMyAppCoreService>().CheckAndProcessResult();
}
await Task.Delay(1000, stoppingToken);
This will neatly dispose every Loop's EFCore-Data Context Object and in my opinion is the cleanest option.这将巧妙地处理每个 Loop 的 EFCore-Data Context Object,在我看来是最干净的选择。
Dependency injection:依赖注入:
services.AddScoped<IMyAppCoreService, MyAppCoreService>();
services.AddDbContext<MyAppCSContext>(options => options.UseSqlServer("Data Source=xx.xxx.xx.xxx;Database=Mydb;User ID = sa;Password=mypassword"), ServiceLifetime.Scoped);
Worker class:工人 class:
public class Worker : BackgroundService
{
IServiceProvider _serviceProvider;
public Worker(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using (var scope = _serviceProvider.CreateScope())
{
scope.ServiceProvider.GetRequiredService<IMyAppCoreService>().CheckAndProcessResult();
}
await Task.Delay(1000, stoppingToken);
}
}
Source https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.0&tabs=visual-studio#consuming-a-scoped-service-in-a-background-task来源https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.0&tabs=visual-studio#sumption-a-scoped-service-in-a-后台任务
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.