.NET Core中多IHostedService实例的不同构造参数注入问题
实现多实例RemoteDevice Worker Service的配置注入方案
问题背景
你当前的场景是:有4台相同设备,需通过TCP连接(每台对应独立IP)通信并获取参数;已经实现了继承自BackgroundService的RemoteDevice类,构造函数为:
public RemoteDevice(RemoteDeviceConfig config, ILogger<RemoteDevice> logger)
类内通过ExecuteAsync方法的while{}循环处理业务逻辑。现在希望基于配置文件构建Worker Service,创建多个RemoteDevice实例,但在Program.cs中多次调用services.AddHostedService<RemoteDevice>()时,发现移除RemoteDeviceConfig时ILogger能正常注入,添加该配置类后却不知如何正确注入。使用的技术栈是.NET Core 3.0 + VS2019 + Worker Service模板项目。
已采纳的解决方案
采纳了@gldraphael的方案,核心思路是通过主Worker类统一管理多设备实例,同时借助ILoggerFactory为每个设备实例创建独立的日志实例,从配置文件批量加载所有设备的配置项。
代码示例
Worker.cs 主服务类
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; public class Worker : BackgroundService { private readonly ILogger<Worker> _logger; private readonly ILoggerFactory _loggerFactory; private readonly List<DeviceConfig> _config; private List<DeviceMainClass> _devices; public Worker(IOptions<List<DeviceConfig>> options, ILogger<Worker> logger, ILoggerFactory loggerFactory) { _config = options.Value; _logger = logger; _loggerFactory = loggerFactory; _devices = new List<DeviceMainClass>(); // 遍历配置,逐个创建设备实例 foreach (var deviceConfig in _config) { _devices.Add(new DeviceMainClass( _loggerFactory.CreateLogger<DeviceMainClass>(), deviceConfig // 可在此添加其他需要注入的参数 )); } } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); await Task.Delay(1000, stoppingToken); } } }
DeviceMainClass(原RemoteDevice类调整)
using Microsoft.Extensions.Logging; using System.Threading; using System.Threading.Tasks; public class DeviceMainClass : BackgroundService { private readonly ILogger<DeviceMainClass> _logger; private readonly DeviceConfig _deviceConfig; public DeviceMainClass(ILogger<DeviceMainClass> logger, DeviceConfig deviceConfig) { _logger = logger; _deviceConfig = deviceConfig; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { // 单台设备的TCP通信、参数获取逻辑写在这里 while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation("Device {deviceIp} running at: {time}", _deviceConfig.IpAddress, DateTimeOffset.Now); // 执行设备专属业务操作 await Task.Delay(5000, stoppingToken); } } }
配置与启动说明
- 配置文件(appsettings.json):添加多设备的配置项
{ "DeviceConfig": [ { "IpAddress": "192.168.1.101", "Port": 8080 }, { "IpAddress": "192.168.1.102", "Port": 8080 }, { "IpAddress": "192.168.1.103", "Port": 8080 }, { "IpAddress": "192.168.1.104", "Port": 8080 } ] }
- Program.cs 配置绑定:
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; 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) => { // 将配置文件中的DeviceConfig节点绑定到List<DeviceConfig> services.Configure<List<DeviceConfig>>( hostContext.Configuration.GetSection("DeviceConfig")); // 注册主Worker服务 services.AddHostedService<Worker>(); }); } }
通过这套方案,就能基于配置文件批量创建设备实例,每个实例都拥有独立的配置和日志记录,完美解决你之前遇到的依赖注入问题。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

