I need to get all connected SerialPorts and poll informations from them. So I wrote a Helper to get the connected SerialPorts, loop them in the Startup.ConfigureService method and add them to the DI Container:
foreach (var serialPort in SystemInformationHelper.GetSerialPorts())
{
services.AddSingleton<IAddress>(sp => new SerialAddress(serialPort));
services.AddSingleton<IConnection, SerialConnection>();
services.AddSingleton<IDevice, PollingDevice>();
}
Then I used constructor injection to get all Connections in my PollingDevice and all Addresses in my Connection Class. See Class Diagram:
Now I gave the Startup Method that is needed to start the Polling process an index to get the correct injected connection and added a HostedService to the Project that is used to control the connected devices.
public class ControllerInitializer : IHostedService
{
private readonly IEnumerable<IDevice> _devices;
public ControllerInitializer(IEnumerable<IDevice> devices)
{
_devices = devices;
}
public Task StartAsync(CancellationToken cancellationToken)
{
for(int i = 0; i < _devices.Count(); i++)
{
_devices.ElementAt(i).Startup(i);
}
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
for (int i = 0; i < _devices.Count(); i++)
{
_devices.ElementAt(i).Shutdown();
}
return Task.CompletedTask;
}
}
It works, but I just started using DI and wanted to know if there is any better solution I don't know about.

Injecting an
IEnumerable<T>of dependencies is a pretty common thing with DI, so that seems perfectly reasonable to me.For example Microsoft uses the same pattern to inject retrieve all the
IHostedService's to callStartAsync/StopAsync. Only difference is they directly retrieve the dependency from theIServiceProviderinstead of injecting it into a constructor.Only thing I'd change is to use a
foreachloop instead of aforloop with theIEnumerable: