我在使用依赖注入(DI
)决定如何最好地构建双向对象管道时遇到了一些困难。
我目前正在试验Ninject
作为DI
容器。
实际上它比这更复杂,因为我正在考虑将两个管道与适配器绑定在一起。
这两个管道由(ITransport
,ITransportSink
)和(IMessageProcessor
,IMessageProcessorSink
)接口对定义如下:
public interface ITransport {
void Connect();
void Disconnect();
void Send(byte[] buffer)
void Receive();
}
public interface ITransportSink {
void OnConnected();
void OnDisconnected();
void OnSent();
void OnReceived(byte[] data);
}
public interface IMessageProcessor {
void SendMessage(string message);
void ReceiveMessage();
}
public interface IMessageProcessorSink {
void OnMessageSent();
void OnMessageReceived(string message);
}
public class TcpTransport : ITransport {
public TcpTransport(
ISocket socket,
ITransportSink sink,
...
) { }
}
public class Program : IMessageProcessorSink {
void Run() {
// Set up serializer as an adapter between transports and message processors
var serializer = new MessageSerializer();
var tcpTransport = new TcpTransport(socket, serializer);
serializer.SetTransport(tcpTransport);
serializer.SetMessageSink(this);
}
void OnMessageReceived(string message) {
Console.Writeline("Received message {0}", message);
}
}
public class MessageSerializer : ITransportSink, IMessageProcessor {
public void OnReceived(byte[] data) {
// Deserializes message and raises IMessageProcessorSink::OnMessageReceived
var message = Deserialize(data);
m_processorSink.OnMessageReceived(message);
}
public void SendMessage(string message) {
// Serializes message to byte and calls ITransport::Send
byte[] data = Serialize(message);
m_transport.Send(data);
}
}
var program = new Program();
program.Run();
问题:
如何使用Ninject
最好地创建管道线和适配器(MessageSerializer)?
问题(进阶):
现在考虑MessageSerializer连接的管道中可能有多个ITransport和多个IMessageProcessors。
使用:
m_kernel.Get<IEnumerable<ITransport>>()
可能无法正确处理运输的订货 因此,我现在需要介绍一些新概念:
ITransportPipeline
ITransportPipelineFactory
IMessageProcessorPipeline
IMessageProcessorPipelineFactory
安装程序将类似于:
var transportPipelineFactory = m_kernel.Get<ITransportPipelineFactory>();
var messagePipelineFactory = m_kernel.Get<IMessageProcessorPipelineFactory>();
var transportPipeline = transportPipelineFactory.CreatePipeline();
var messageProcessorPipeline = messagePipelineFactory.CreatePipeline();
var serializer = new MessageSerializer();
transportPipeline.Append(serializer);
messageProcessorPipeline.InsertAt(0,serializer);
此时我正在编写如此多的手动接线代码,DI
容器似乎没有多大帮助。是否有DI
个容器功能或绑定可以帮到这里?
我感觉设计是错误的,或者这不是DI
容器要解决的情况。
答案 0 :(得分:0)
我花了一段时间,但我找到了一种方法让它发挥作用。 诀窍是将配置逻辑包装在更高级别的概念对象构造函数中:
public class AggregatePipeline
{
private ITransportPipeline m_transportPipelines;
private IMessageProcessorPipeline m_messagePipeline;
private MessageSerializer m_serializer;
public AggregatePipeline(
ITransportPipeline transportPipeline,
IMessageProcessorPipeline messagePipeline,
MessageSerializer serializer)
{
transportPipeline.Append(serializer);
messagePipeline.Prepend(serializer);
m_transportPipeline = transportPipeline;
m_messagePipeline = messagePipeline;
m_serializer = serializer;
}
}
因为每个项都是构造函数参数,所以不需要对内核进行显式调用。 添加几个绑定:
Bind<AggregatePipeline>().ToSelf()
.WithConstructorArgument("transportPipeline", (ctx) =>
{
return ctx.Kernel.Get<ITransportPipelineFactory>().CreatePipeline();
})
.WithConstructorArgument("messagePipeline", (ctx) =>
{
return ctx.Kernel.Get<IMessageProcessorPipelineFactory>().CreatePipeline();
});
Bind<MessageSerializer>().ToSelf();
然后通过内核创建外部对象:
m_kernel.Get<AggregatePipeline>();
似乎解决了没有服务位置反模式的问题。