在ASP.NET Core Worker服务中注入依赖关系

问题描述 投票:0回答:1

我在.NET Core Worker服务中遇到了一些依赖注入问题,请看下面的代码。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();
}

请看下面的代码 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);
    }
}

当我运行上述查询时,我得到了以下查询。

验证服务描述符时出错

服务类型。MyApp.CS.Business.Facade.IMyAppCoreService Lifetime: Scoped ImplementationType.ImplementationType: MyApp.CS.Business.Services.Facade.IMyAppCoreService MyApp.CS.Business.Services.MyAppCoreService"。在尝试激活 "MyApp.CS.Business.Services.MyAppCoreService "时,无法解析'MyApp.CS.Data.Facade.ICommonRepository'类型的服务。

请您告诉我,我哪里做错了?

EDIT: 当我把所有的接口都注册到它的类中后,我得到了新的错误,如下所示。

在验证服务描述符 "ServiceType.Hosting.Implement "时出错。Microsoft.Extensions.HostedService Lifetime: Singleton ImplementationType.MyApp_CoreService.Worker.IHostedService MyApp_CoreService.Worker'。不能从单人'Microsoft.Extensions.HostedService'中消耗作用域服务'MyApp.CS.Business.Facade.IMyAppCoreService'。

c# asp.net-core .net-core windows-services backgroundworker
1个回答
0
投票

你注入了Serivce IMyAppCoreService 为 "范围"。范围内的服务只能由 ScopedServiceProvider.

我的第一个猜测是,你并不是故意的--你的意思是将你的服务注入为Singleton。

services.AddSingleton<IMyAppCoreService, MyAppCoreService>();

但这可能行不通,因为你使用的是EF Core,它将Context-like类注入为scoped。你有两个选择。

  1. 有EF Core注入它的上下文类为瞬态。我不建议这样做,因为你要负责处理它。如果你想通过它,这是如何做到这一点(Startup.cs Program.cs)。
services.AddDbContext<YourContext>(opts => { ...config...}, ServiceLifetime.Transient);
  1. 手动创建一个范围

有一个... IServiceProvider 属性,称为ServiceProvider注入到 Worker 而是 的服务。

在ExecuteAsync-Loop中,这将整齐地处理每个Loop的EFCore-Data Context对象,在我看来是最干净的选择。

_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
using (var scope = ServiceProvider.CreateScope())
{
  scope.ServiceProvider.GetRequiredService<IMyAppCoreService>().CheckAndProcessResult();
}
await Task.Delay(1000, stoppingToken);

这将整齐地处理每个Loop的EFCore -Data Context对象,在我看来是最干净的选择。

© www.soinside.com 2019 - 2024. All rights reserved.