【问题标题】:Creating object pipelines using dependency injection (Ninject)使用依赖注入创建对象管道 (Ninject)
【发布时间】:2014-04-10 01:20:59
【问题描述】:

我在决定如何最好地使用依赖注入 (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 容器打算解决的场景。

【问题讨论】:

    标签: c# dependency-injection ninject


    【解决方案1】:

    花了我一段时间,但我找到了一种让它工作的方法。 诀窍是将配置逻辑包装在更高级别的概念对象构造函数中:

    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>();
    

    似乎解决了没有服务位置反模式的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 2016-10-08
      • 1970-01-01
      相关资源
      最近更新 更多