[英]Creating object pipelines using dependency injection (Ninject)
我在決定如何最好地使用依賴注入( 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和多個IMessageProcessor。
使用方法:
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
容器要解決的情況。
花了我一段時間,但我找到了使它工作的一種方法。 訣竅是將配置邏輯包裝在更高級別的概念對象構造函數中:
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>();
似乎解決了沒有服務位置反模式的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.