.NET Core 3 工作服务设置依赖注入

9

我在.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.Worker' 时无法解析类型为 'WorkerService1DeleteMe.ConfigChunk' 的服务。

我觉得我可能错过了一些非常明显的东西,但必须承认我有点迷茫。我观察到,如果我使用 services.AddSingleton 而不是 services.Configure ,整个事情就可以工作,但如果能让 Configure 方法工作起来,我更喜欢它的模式和重新加载功能。

1个回答

16

可选项较少。

使用当前配置更新工作者以使用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);
        }
    }
}

或者保留工作人员不变,更新配置以允许将类本身注入。

    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,同时仍然允许选项功能生效,并且不会将工作器与框架问题紧密耦合。

哇,太棒了伙计,非常感谢你,运行得很好! - Adrian Hand
这帮助我将一个状态对象注入到一个组合的工作器/ WebAPI 项目中,从而使工作器服务状态信息能够通过 WebAPI 公开。谢谢。 - Mike
所以我之前使用的是: IConfiguration configuration = hostContext.Configuration; Configuration appConfiguration = configuration.GetSection("AppSettings").Get<Configuration>(); services.AddSingleton(appConfiguration);这对我来说很好用,但当我像你的例子一样切换到使用IOptions时services.Configure<Configuration>(hostContext.Configuration.GetSection("AppSettings"));它没有从appSettings.json中加载我的AppSettings部分。我错过了什么?此外,它是否支持appSettings.Development.json和appSettings.Production.json,文件更改时是否重新加载? - Chris Ward
我能够在这里回答自己的问题:https://dev59.com/87fna4cB1Zd3GeqPny6l?noredirect=1&lq=1看一下.ConfigureAppConfiguration((hostContext, config)部分,这回答了我所有关于可选和重新加载的问题,并且让我的工作正常运行。 - Chris Ward

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接