Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Ninject到泛型类型的映射_C#_Dependency Injection_Ninject_Inversion Of Control - Fatal编程技术网

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