簡體   English   中英

ASP.NET Core Worker 服務中的依賴注入

[英]Dependency Injection in ASP.NET Core Worker Service

我在 .NET Core Worker Service 中遇到了一些依賴注入問題。 請參閱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);
    }
}

當我運行上面的查詢時,我得到了下面的查詢。

驗證服務描述符時出錯

ServiceType:MyApp.CS.Business.Facade.IMyAppCoreService Lifetime:Scoped ImplementationType:MyApp.CS.Business.Services.MyAppCoreService':嘗試激活“MyApp”時無法解析“MyApp.CS.Data.Facade.ICommonRepository”類型的服務.CS.Business.Services.MyAppCoreService'。

你能告訴我我哪里做錯了嗎?

編輯:在我用它的 class 注冊所有接口之后。 然后我得到如下新錯誤。

驗證服務描述符“ServiceType:Microsoft.Extensions.Hosting.IHostedService Lifetime:Singleton ImplementationType:MyApp_CoreService.Worker”時出錯:無法使用 Z2ED500A3529637175E675A8791B7C56.E 中的范圍服務“MyApp.CS.Business.Facade.IMyAppCoreService”托管服務”。

您將IMyAppCoreService作為 Scoped 注入。 Scoped Services 只能由ScopedServiceProvider

我的第一個猜測是您不是故意的-您打算將服務注入為 Singleton:

services.AddSingleton<IMyAppCoreService, MyAppCoreService>();

但是,這可能不起作用,因為您使用的是 EF Core,它將其 Context-like 類作為作用域注入。 你有兩個選擇:

  1. 讓 EF Core 將其上下文 class 作為瞬態注入。 我不建議這樣做,因為您將負責處理它。 如果你想 go 通過它,這是如何做到的(Startup.cs / Program.cs):
services.AddDbContext<YourContext>(opts => { ...config...}, ServiceLifetime.Transient);
  1. 手動創建 scope:

將一個名為 ServiceProvider 的IServiceProvider屬性注入Worker而不是您的服務。

在 ExecuteAsync 循環中:

_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 Object,在我看來是最干凈的選擇。

依賴注入:

 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);

工人 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);
    }
}

來源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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM