如何使用Ninject修饰绑定到多个具体类型的接口

时间:2012-11-07 21:55:56

标签: ninject decorator

所以,我有一个消息总线通过Ninject实例化消息处理程序。我想用交叉问题来装饰我的处理程序,例如日志记录,事务管理等。

我设置了这样的绑定:

kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>()
    .WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>));

每当我有一个特定消息类型的单个处理程序时,它就会非常有效。但是,当我定义了多个处理程序时:

kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>()
    .WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind<IMessageHandler<int>>().To<IntHandlerTwo>()
    .WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>));

Ninject将找到并将装饰器注入消息总线,然后尝试将两个处理程序注入装饰器构造函数中。

public HandlerDecorator(IMessageHandler<T> handler)

您可能在想,为什么我不修改我的装饰器来接受处理程序列表?我想到了这一点,但这违背了处理程序的目的。我希望能够轻松地将多个装饰器连接在一起。 IMessageHandler<T>的每个实例都应该获得一个全新的处理程序链。

我在GitHub上发布了an example测试库,应该说明我在这里谈论的内容。

在Ninject中有没有办法做到这一点?

2 个答案:

答案 0 :(得分:3)

使用

kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>().WhenParentNamed("One");
kernel.Bind<IMessageHandler<int>>().To<IntHandlerTwo>().WhenParentNamed("Two");
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>)).Named("One");
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>)).Named("Two");

另请注意,大多数总线框架都有一些方法可以为消息处理程序做装饰。可以先看看那里。

答案 1 :(得分:0)

您应该将这些处理程序包装在composite

public class CompositeMessageHandler<T> : IMessageHandler<T>
{
    private readonly IEnumerable<IMessageHandler<T>> handlers;

    CompositeMessageHandler(IEnumerable<IMessageHandler<T>> handlers)
    {
        this.handlers = handlers;
    }

    public void Handle(T message)
    {
        foreach (var handler in this.handlers)
        {
            handler.Handle(message);
        }
    }
}

这个复合材料可以再次注入装饰器。或许你应该反过来做:用装饰器包裹每个处理程序并将它们包装到复合材料中。

我不知道如何用Ninject注册这个。