Sim*_*mon 8 .net c# visual-studio-2019 .net-core-3.0
我的环境有 4 个相同的设备,我必须连接这些设备并通过 TCP 连接请求一些参数(每个设备都有其 IP 地址)。我已经为需要一些参数的单个设备实现了一个类(如 IP 地址、端口、轮询间隔等...)
该类实现BackgroundService接口并具有如下所示的构造函数:
public RemoteDevice(RemoteDeviceConfig config, ILogger<RemoteDevice> logger)
Run Code Online (Sandbox Code Playgroud)
在类内部有一个ExecuteAsync方法的实现,内部有一个while{}循环,它执行所有逻辑。
我想构建一个基于配置文件(例如带有设备数组的配置文件)处理该类的多个实例的工作服务
在 Program.cs 中我会这样做:
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSystemd()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<RemoteDevice>(); //First device
services.AddHostedService<RemoteDevice>(); //Second device
...
services.AddHostedService<RemoteDevice>(); //n-th device
});
...
//Methods to load configuration
...
Run Code Online (Sandbox Code Playgroud)
如果没有RemoteDeviceConfig构造函数参数,则会ILogger注入,但如果我添加它,我不知道如何注入我的RemoteDeviceConfig类
我错了什么?
我将 .NET Core 3.0 与 VS2019 和工作人员服务模板项目结合使用。
更新 - 接受的答案
我已经接受了@gldraphael 答案,并且我将添加有关答案评论中指定的日志记录部分的一些详细信息。
问题:在主 Worker 类中实例化的类中使用 ILogger 实现。
解决方案:在Worker类中注入ILoggerFactory并使用它为子类创建记录器
DeviceMainClass和DeviceConfig分别是通用设备管理器及其配置。
工人.cs
List<DeviceMainClass> devices;
//Pass ILoggerFactory to worker constructor for Dependency Injection
//On worker start, instantiate all subclasses and create logger for each class
public Worker(IOptions<List<DeviceConfig>> options, ILogger<Worker> logger, ILoggerFactory loggerFactory)
{
devices = new List<DeviceMainClass>();
foreach(var device in _config)
{
devices.Add(new DeviceMainClass(_loggerFactory.CreateLogger<DeviceMainClass>(),...other parameters));
}
_logger = logger;
_loggerFactory = loggerFactory;
_config = options.Value;
}
...
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
//***for testing purposes only, repeats every second***
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
Run Code Online (Sandbox Code Playgroud)
设备主类
private readonly ILogger<DeviceMainClass> _logger;
//Use
public DeviceMainClass(ILogger<DeviceMainClass> logger, ...other parameters)
{
_logger = logger;
...
}
Run Code Online (Sandbox Code Playgroud)
你想做这样的事情:
应用程序设置.json
{
"Devices": [
{ "Name": "D1" },
{ "Name": "D2" },
{ "Name": "D3" },
{ "Name": "D4" }
]
}
Run Code Online (Sandbox Code Playgroud)
CreateHostBuilder():
{
"Devices": [
{ "Name": "D1" },
{ "Name": "D2" },
{ "Name": "D3" },
{ "Name": "D4" }
]
}
Run Code Online (Sandbox Code Playgroud)
工人:
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly List<DeviceConfig> config;
public Worker(IOptions<List<DeviceConfig>> options, ILogger<Worker> logger)
{
config = options.Value;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
foreach(var device in config)
{
// TODO: Process each device here
_logger.LogInformation("Processing device {name}", device.Name);
}
await Task.Delay(1000, stoppingToken);
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您当前的RemoteDevice类有状态信息,请List<RemoteDevice>在工作线程中创建一个并从配置中初始化。