C# Ninject到泛型类型的映射
我有一组由事件处理程序处理的事件,如下所示:C# Ninject到泛型类型的映射,c#,dependency-injection,ninject,inversion-of-control,C#,Dependency Injection,Ninject,Inversion Of Control,我有一组由事件处理程序处理的事件,如下所示: var single_consumer = kernel.Get<IConsume<DeliveryCreated>>(); 事件处理程序: public class DeliveryEventHandlers : IConsume<DeliveryCreated>, IConsume<DeliveryUpdated>{ readonly IDocumentSession _documentSess
var single_consumer = kernel.Get<IConsume<DeliveryCreated>>();
事件处理程序:
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)
{
//...
}
...
我需要编写一个Ninject绑定,它将根据事件类型的请求,为我提供使用这些事件的事件处理程序。这就是我想到的:
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 ^
});
}
}
public void bindEventHandler(IContext上下文){
Bind(x=>
{
x、 FromAssemblyContaining(typeof(DeliveryCreated))
.SelectAllClasses()
.继承自()
.BindWith(新的EventBindingGenerator());
});
}
公共类EventBindingGenerator:IBindingGenerator
{
公共IEnumerable CreateBindings(类型类型,IBindingRoot bindingRoot)
{
返回bindingRoot.Bind(x=>
{
x、 FromAssemblyContaining(类型(DeliveryEventHandlers))
.SelectAllClasses()
.继承自(IConsume);
//这部分^
});
}
}
但这实际上不会编译-我在注释://这部分上面的一行遇到了一个障碍^
我需要查询:
_context.Get<DeliveryCreated>()
\u context.Get()
并收到一份送货单
任何帮助都将不胜感激
谢谢,
H您可以手动扫描程序集并注册实现
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);
}
}
foreach(在assembly.GetTypes()中键入Type,其中(x=>x.IsClass))
{
弗雷奇(
中的var@接口
type.GetInterfaces()
.Where(i=>i.IsGenericType&&i.GetGenericTypeDefinition()==typeof(IConsume)))
{
Bind(@interface.To)(类型);
}
}
如果您知道活动将只有一个使用者,请使用以下命令:
var single_consumer = kernel.Get<IConsume<DeliveryCreated>>();
var single_consumer=kernel.Get();
如果可能有多个消费者,请使用以下方法获取所有消费者:
var all_consumers = kernel.GetAll<IConsume<DeliveryCreated>>();
var all_consumers=kernel.GetAll();
使用约定扩展功能实际上可以很容易地解决这一问题:
kernel.Bind(x => x.FromAssemblyContaining(typeof(DeliveryCreated))
.IncludingNonePublicTypes() // may not be needed in your case
.SelectAllClasses()
.InheritedFrom(typeof(IConsume<>))
.BindAllInterfaces());
再一次,我验证了它确实有效。感谢您如此快速地回答Yacoub,但此解决方案不起作用。它实际上将我的处理程序绑定到事件类的IEvent接口。我不明白你的意思。你能再解释一下它做了什么吗?谢谢你的回复。这看起来是一个构造良好的答案-我还没有机会测试它-只是检查一下,我需要这样查询:_context.Get()不是:_context.Get()-这样行吗?@HCdev。如果执行
Get
操作,将返回T
。您的DeliveryEventHandlers
未实现DeliveryCreated
,无法将其强制转换为DeliveryCreated
。这是根据语言规范,因此无论您如何尝试,都无法实现这一点。您必须执行\u context.Get()
。您能否提供(伪代码可以)在检索到DeliveryCreatedEventHandler
后应该如何处理它?
kernel.Get<IConsume<DeliverCreated>>().Should().BeOfType<DeliveryEventHandlers>();
kernel.Get<IConsume<DeliveryUpdated>>().Should().BeOfType<DeliveryEventHandlers>();
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));