![](/img/trans.png)
[英]How to register multiple implementation for same interface using .NET CORE DI
[英]How to register and use different implementation of same interface?
假设我有这种情况:
using System.Linq; using NUnit.Framework; public interface IChannel { void Write(double value); } public class Channel: IChannel { private readonly int channelNumber; public Channel(int channelNumber) { Requires.That(channelNumber >= 0, "channelNumber >= 0"); this.channelNumber = channelNumber; } private int calls; public void Write(double value) { System.Console.WriteLine("{0} wrote on channel {1} [#{2}]", value.ToString(), channelNumber, ++calls); } } public interface IService { void Do(); } public class ServicePiGreek: IService { private readonly IChannel channel; public ServicePiGreek(IChannel channel) { Requires.IsNotNull(channel, "channel"); this.channel = channel; } public void Do() { channel.Write(3.14); } } public class ServiceEuler: IService { private readonly IChannel channel; public ServiceEuler(IChannel channel) { Requires.IsNotNull(channel, "channel"); this.channel = channel; } public void Do() { channel.Write(2.71); } }
所以我会创建两个ServicePiGreek,通道0和1,以及一个ServiceEuler通道0:
[TestFixture] public class Tests { [Test]public void without_simpleinjector() { var ch0 = new Channel(0); var s0 = new ServicePiGreek(ch0); var s1 = new ServicePiGreek(new Channel(1)); var s2 = new ServiceEuler(ch0); s0.Do(); s1.Do(); s2.Do(); }
我想到了这个:
[Test]public void with_simpleinjector() { SimpleInjector.Container container = new SimpleInjector.Container(); container.RegisterAll(new Channel(0), new Channel(1)); container.RegisterAll(GetAllServices(container)); foreach (var service in container.GetAllInstances()) { service.Do(); } } private System.Collections.Generic.IEnumerable GetAllServices(SimpleInjector.Container container) { yield return new ServicePiGreek(container.GetAllInstances().ElementAt(1)); yield return new ServicePiGreek(container.GetAllInstances().ElementAt(0)); yield return new ServiceEuler(container.GetAllInstances().ElementAt(0)); }
有没有人对如何做到这一点有更好的想法?
您的用例不是常用的,因为您在同一列表中具有多次相同的实现(作为瞬态),并且需要使用IChannel
接口的不同实现来填充它。
我无法调查你的设计,但你现在如何注册这些类型是有道理的。 您注册了一个动态IEnumerable,它在迭代时回调容器。 很高兴看到您正在使用Simple Injector的一个较新功能,使用ElementAt
(即O(1)操作)通过索引获取项目,因为返回的集合实现了IList<T>
。
您可以执行以下操作以使代码更具可读性:
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));
}
或者,当IService
实现可以是单例时,您将能够执行以下操作:
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();
}
您可以在工厂后面抽象,而不是按索引请求元素,例如:
interface IChannelProvider
{
IChannel GetBlueChannel();
IChannel GetRedChannel();
}
但是,这取决于您的情况是否有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.