4

所以,我有一个通过 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 上发布了一个示例测试库,它应该能说明我在这里所说的内容。

Ninject 有什么方法可以做到这一点吗?

4

2 回答 2

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

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

于 2012-11-16T11:46:18.190 回答
0

您应该将这些处理程序包装在一个组合中:

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 注册它。

于 2012-11-08T10:33:19.073 回答