所以,我有一个消息总线通过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中有没有办法做到这一点?
答案 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注册这个。