gpt4 book ai didi

c# - 如何注册和使用相同接口(interface)的不同实现?

转载 作者:行者123 更新时间:2023-12-04 12:26:48 25 4
gpt4 key购买 nike

假设我有这个场景:

使用 System.Linq;
使用 NUnit.Framework;
公共(public)接口(interface) IChannel {
无效写入(双值);
}

公共(public)类 channel :IChannel {
私有(private)只读 int channelNumber;
公共(public) channel (int channelNumber){
Requires.That(channelNumber >= 0, "channelNumber >= 0");
this.channelNumber = channelNumber;
}
私有(private) int 调用;
公共(public)无效写入(双值){
System.Console.WriteLine("{0} 在 channel {1} 上写了 [#{2}]", value.ToString(), channelNumber,++calls);
}
}

公共(public)接口(interface) IService {
空做();
}

公共(public)类 ServicePiGreek:IService {
私有(private)只读 IChannel channel ;
公共(public) ServicePiGreek(IChannel channel ){
Requires.IsNotNull(channel, "channel");
this.channel = channel ;
}
公共(public)无效做(){
channel .写入(3.14);
}
}
公共(public)类 ServiceEuler: IService {
私有(private)只读 IChannel channel ;
公共(public) ServiceEuler(IChannel channel ){
Requires.IsNotNull(channel, "channel");
this.channel = channel ;
}
公共(public)无效做(){
channel .写入(2.71);
}
}

所以我会创建两个带有 channel 0 和 1 的 ServicePiGreek 和一个带有 channel 0 的 ServiceEuler:

[测试夹具]
公共(public)类测试{
[测试]public void without_simpleinjector() {
var ch0 = 新 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();
}

我想到了这个:

[测试]public void with_simpleinjector() {
SimpleInjector.Container container = new SimpleInjector.Container();
container.RegisterAll(new Channel(0), new Channel(1));
container.RegisterAll(GetAllServices(container));

foreach(容器中的var服务.GetAllInstances()){
服务.Do();
}
}

私有(private) System.Collections.Generic.IEnumerable GetAllServices(SimpleInjector.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));
}

有没有人对如何实现这一点有更好的想法?

最佳答案

您的用例不是通常的用例,因为您在同一个列表中多次(作为 transient )具有相同的实现,并且需要用 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();
}

但是,这取决于您的方案是否有效。

关于c# - 如何注册和使用相同接口(interface)的不同实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16482434/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com