Your use case is not a usual one, since you have the same implementation multiple times (as transient) in the same list and need to fill it with different implementations of the IChannel
interface.
I can't look into your design, but how you're registering the types right now makes sense. You register a dynamic IEnumerable that calls back upon the container upon iteration. It's nice to see that you're using one of the newer features of Simple Injector to get items by their index using ElementAt
which is an O(1) operation, since the returned collection implements IList<T>
.
You could do the following to make the code more readable:
private IEnumerable<IService> GetAllServices(Container container) {
var channels = container.GetAllInstances<IChannel>();
yield return new ServicePiGreek(channels.ElementAt(0));
yield return new ServicePiGreek(channels.ElementAt(1));
yield return new ServiceEuler(channels.ElementAt(0));
}
Or when the IService
implementations can be singleton, you would be able to do the following:
var container = new SimpleInjector.Container();
var blueChannel = new Channel(0);
var redChannel = new Channel(1);
container.RegisterAll<IService>(
new ServicePiGreek(blueChannel),
new ServicePiGreek(redChannel),
new ServiceEuler(blueChannel),
);
foreach (var service in container.GetAllInstances<IService>()) {
service.Do();
}
Instead of requesting elements by their index, you could abstract this behind a factory, for instance:
interface IChannelProvider
{
IChannel GetBlueChannel();
IChannel GetRedChannel();
}
But, it depends on your scenario if this works.