Внедрение зависимостей настроек службы .NET Core 3 Worker - PullRequest
1 голос
/ 08 октября 2019

У меня есть следующее, успешно работающее в .NET Core 2, но оно не работает в .NET Core 3.

Я создал новый проект Worker Service .Net Core 3 с нуля и добавилтолько минимум, чтобы воссоздать мою ошибку.

Вот моя точка входа в Program.cs

namespace WorkerService1DeleteMe
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.Configure<ConfigChunk>(hostContext.Configuration.GetSection("ConfigChunk"));
                    services.AddHostedService<Worker>();
                });
    }

    public class ConfigChunk
    {
        public string Server { get; set; }
    }
}

Таким образом, к CreateHostBuilder добавлена ​​одна строка, к методу Configure и новому классу ConfigChunk внизу, чтобы соответствовать схеме раздела в appsettings.json .

Наконец, расширение параметровв конструктор Worker, чтобы позволить ему потреблять SettingsChunk:

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly ConfigChunk _config;

    public Worker(ILogger<Worker> logger, ConfigChunk config)
    {
        _logger = logger;
        _config = config;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }
}

Как упоминалось, это работает нормально в NET Core 2, но в 3 он не работает с:

Невозможноразрешить службу для типа «WorkerService1DeleteMe.ConfigChunk» при попытке активировать «WorkerService1DeleteMe.Worker».

Я чувствую, что упускаю что-то ослепительно очевидное, но должен признаться, что я в растерянности. Что я заметил, так это то, что я могу заставить все это работать, набрав services.AddSingleton вместо services.Configure, но я очень предпочитаю функциональность шаблонов и перезагрузки подхода Configure, если смогу заставить его работать.

1 Ответ

5 голосов
/ 08 октября 2019

Доступно несколько вариантов.

При использовании текущего работника обновления конфигурации IOptions<TOptions>

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly ConfigChunk _config;

    public Worker(ILogger<Worker> logger, IOptions<ConfigChunk> config) {
        _logger = logger;
        _config = config.Value;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
        while (!stoppingToken.IsCancellationRequested) {
            _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }
}

Или оставьте работника как есть и обновите конфигурацию, чтобы позволить самому классу бытьinjected.

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) => {
                services.Configure<ConfigChunk>(hostContext.Configuration.GetSection("ConfigChunk"));
                services.AddHostedService<Worker>();
                services.AddTransient<ConfigChunk>(_ => _.GetRequiredService<IOptions<ConfigChunk>>().Value);

            });

Во втором примере будет разрешено явное внедрение ConfigChunk, в то же время позволяя задействовать функции опций, и он не будет тесно связан с проблемами рабочей среды.

...