C# 使用依赖项注入(Ninject)创建对象管道
我在决定如何最好地使用依赖项注入(C# 使用依赖项注入(Ninject)创建对象管道,c#,dependency-injection,ninject,C#,Dependency Injection,Ninject,我在决定如何最好地使用依赖项注入(DI)构建双向对象管道时遇到了一些困难 我目前正在将Ninject作为DI容器进行试验 它实际上比这更复杂,因为我正在考虑用适配器将两个管道绑定在一起 这两条管道由以下接口对(ITransport,ITransportSink)和(IMessageProcessor,IMessageProcessorSink)定义: public interface ITransport { void Connect(); void Disconnect(); vo
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)
问题(高级):现在考虑在MeaseSerialAlgisher连接的管道中可以有多个ITANCANT和多个IDESCAGE处理器。 使用:
m_kernel.Get<IEnumerable<ITransport>>()
然后,安装程序将类似于:
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);
var transportPipelineFactory=m_kernel.Get();
var messagePipelineFactory=m_kernel.Get();
var transportPipeline=transportPipelineFactory.CreatePipeline();
var messageProcessorPipeline=messagePipelineFactory.CreatePipeline();
var serializer=new MessageSerializer();
transportPipeline.Append(序列化程序);
messageProcessorPipeline.InsertAt(0,序列化程序);
在这一点上,我编写了太多的手动接线代码,以至于DI
容器似乎没有多大帮助。是否有DI
容器特性或绑定可以在这里提供帮助
我觉得要么设计错误,要么这不是
DI
容器想要解决的问题。花了我一段时间,但我找到了一种方法让它工作。
诀窍是将配置逻辑包装在更高级别的概念对象构造函数中:
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();
Bind().ToSelf()
.WithConstructorArgument(“运输管道”(ctx)=>
{
返回ctx.Kernel.Get().CreatePipeline();
})
.WithConstructorArgument(“messagePipeline”,(ctx)=>
{
返回ctx.Kernel.Get().CreatePipeline();
});
Bind().ToSelf();
然后通过内核创建外部对象:
m_kernel.Get<AggregatePipeline>();
m_kernel.Get();
似乎解决了没有服务位置反模式的问题
m_kernel.Get<AggregatePipeline>();