c# - 在 .NET Core 中使用不同的构造函数参数(DI 和非 DI)注册多个 IHostedService 实例

标签 c# .net visual-studio-2019 .net-core-3.0

我有一个环境,有 4 个相同的设备,我必须连接到这些设备并通过 TCP 连接请求一些参数(每个设备都有其 IP 地址)。
我为需要一些参数的单个设备实现了一个类(如 IP 地址、端口、轮询间隔等...)

该类实现 BackgroundService接口(interface)并有一个像下面这样的构造函数:

public RemoteDevice(RemoteDeviceConfig config, ILogger<RemoteDevice> logger)

在这个类中有一个 ExecuteAsync 的实现。带有 while{} 的方法在里面循环,这完成了所有的逻辑。

我想基于配置文件(例如,带有一组设备的配置文件)构建一个处理该类的多个实例的 Worker Service

在 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 
...

没有 RemoteDeviceConfig构造函数参数,ILogger被注入(inject),但如果我添加它,我不知道如何注入(inject)我的 RemoteDeviceConfig类(class)

我怎么了?

我将 .NET Core 3.0 与 VS2019 和 Worker Service Template 项目一起使用。

更新 - 接受的答案

我已经接受@gldraphael answer ,我会添加一些有关答案评论中指定的日志记录部分的详细信息。

问题:在主 Worker 类中实例化的类中使用 ILogger 实现。

解决方案:在 Worker 类中注入(inject) ILoggerFactory 并使用它为子类创建记录器
DeviceMainClassDeviceConfig分别是通用设备管理器及其配置。

worker .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);
    }
}

设备主类
private readonly ILogger<DeviceMainClass> _logger;

//Use
public DeviceMainClass(ILogger<DeviceMainClass> logger, ...other parameters)
{
    _logger = logger;
    ...
}

最佳答案

你想做这样的事情:

appsettings.json

{
  "Devices": [
    { "Name": "D1" },
    { "Name": "D2" },
    { "Name": "D3" },
    { "Name": "D4" }
  ]
}
CreateHostBuilder() :

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


worker :
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);
            }
        }
    }

如果您当前 RemoteDevice类有状态信息,创建List<RemoteDevice>在工作程序中并从配置初始化。

关于c# - 在 .NET Core 中使用不同的构造函数参数(DI 和非 DI)注册多个 IHostedService 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58624503/

相关文章:

sql-server - Visual Studio 2019 - SSDT

C# 为什么我可以在常量上调用对象扩展方法?

c# - 另一个程序集中的 MVVM 行为

c# - BuildManager 解析页面继承

c# - 为什么不在 System.Double 和 System.Long 上使用 volatile?

.net - 如何使用 Net.TCP 从 1 个客户端实现对 WCF 服务的并发请求

c# - 如何在 C# 项目的预构建和构建后事件中获取最新的 windows sdk 版本路径?

angular - 在Visual Studio 2019中创建新的Asp.Net Core 2.1 Angular项目时无法选择单个用户帐户

c# - 无法编码包含 union 的结构

c# - 将 64 位数组转换为 Int64 或 ulong C#