我有一堆事件由事件处理程序处理,如下所示:
事件处理程序:
public class DeliveryEventHandlers :
IConsume<DeliveryCreated>,
IConsume<DeliveryUpdated>{
readonly IDocumentSession _documentSession;
public DeliveryEventHandlers(IDocumentSession documentSession)
{
_documentSession = documentSession;
}
public void Consume(DeliveryCreated @event)
{
//...
}
public void Consume(DeliveryUpdated @event)
{
//...
}
...
活动:
public class DeliveryCreated : IEvent
{
public Guid DeliveryId { get; set; }
...
}
public class DeliveryUpdated : IEvent
{
public Guid DeliveryId { get; set; }
...
}
我需要编写一个Ninject绑定,根据Event类型的请求,给我一个消耗这些事件的事件处理程序。这就是我想出的:
public void BindEventHandlers(IContext context) {
Kernel.Bind(x =>
{
x.FromAssemblyContaining(typeof(DeliveryCreated))
.SelectAllClasses()
.InheritedFrom<IEvent>()
.BindWith(new EventBindingGenerator());
});
}
public class EventBindingGenerator : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
yield return bindingRoot.Bind(x =>
{
x.FromAssemblyContaining(typeof(DeliveryEventHandlers))
.SelectAllClasses()
.InheritedFrom(IConsume<typeof(type)>);
// This Part ^
});
}
}
但这实际上不会编译 - 我在评论上面的一行上遇到了障碍://这部分^
我需要查询:
_context.Get<DeliveryCreated>()
并收到一个DeliveryCreatedEventHandler。
任何帮助都会受到赞赏!!
谢谢, ħ
答案 0 :(得分:1)
使用约定扩展功能实际上可以很容易地解决这个问题:
kernel.Bind(x => x.FromAssemblyContaining(typeof(DeliveryCreated))
.IncludingNonePublicTypes() // may not be needed in your case
.SelectAllClasses()
.InheritedFrom(typeof(IConsume<>))
.BindAllInterfaces());
以下测试成功(语法来自FluentAssertions):
kernel.Get<IConsume<DeliverCreated>>().Should().BeOfType<DeliveryEventHandlers>();
kernel.Get<IConsume<DeliveryUpdated>>().Should().BeOfType<DeliveryEventHandlers>();
或者,如果您想确保不希望将IConsume<...>
实现绑定到不必要的更多类型,则可以按如下方式替换BindAllInterfaces
语句:
private static IEnumerable<Type> SelectConsumeInterfacesOnly(
Type type, IEnumerable<Type> baseTypes)
{
var matchingTypes = baseTypes.Where(t =>
t.IsGenericType
&& t.GetGenericTypeDefinition() == typeof (IConsume<>));
return matchingTypes;
}
kernel.Bind(x => x.FromThisAssembly()
.IncludingNonePublicTypes()
.SelectAllClasses()
.InheritedFrom(typeof(IConsume<>))
.BindSelection(SelectConsumeInterfacesOnly));
同样,我已经确认它确实有效。
答案 1 :(得分:0)
您可以手动扫描程序集并注册实现IConsumer<>
接口的所有类。像这样:
foreach (Type type in assembly.GetTypes().Where(x => x.IsClass))
{
foreach (
var @interface in
type.GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IConsume<>)))
{
kernel.Bind(@interface).To(type);
}
}
如果您知道该活动的单个消费者,请使用以下内容:
var single_consumer = kernel.Get<IConsume<DeliveryCreated>>();
如果可能有多个消费者,请使用以下内容获取所有消费者:
var all_consumers = kernel.GetAll<IConsume<DeliveryCreated>>();