簡體   English   中英

使用依賴注入(Ninject)創建對象管道

[英]Creating object pipelines using dependency injection (Ninject)

我在決定如何最好地使用依賴注入( DI )構造雙向對象管道方面遇到一些困難。

我目前正在嘗試將Ninject用作DI容器。

實際上,這要復雜得多,因為我正在考慮使用適配器將兩個管道綁定在一起。

這兩個管道由下面的( ITransportITransportSink )和( IMessageProcessorIMessageProcessorSink )接口對定義:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM