Generics Autofac-解析通用接口

Generics Autofac-解析通用接口,generics,asp.net-core,autofac,Generics,Asp.net Core,Autofac,我在解决实现泛型接口的类型时遇到问题。以下是事件类、泛型接口和实现泛型接口的类 public class ExampleEvent : IDomainEvent { public ExampleEvent() { DateTimeEventOccurred = DateTime.Now; } public DateTime DateTimeEventOccurred { get; private set; } } public interfac

我在解决实现泛型接口的类型时遇到问题。以下是事件类、泛型接口和实现泛型接口的类

public class ExampleEvent : IDomainEvent
{
    public ExampleEvent()
    {
        DateTimeEventOccurred = DateTime.Now;
    }

    public DateTime DateTimeEventOccurred { get; private set; }
}

public interface IHandle<T> where T : IDomainEvent
{
    void Handle(T args);
}

public class ExampleEventHandler : IHandle<ExampleEvent>
{
    public ExampleEventHandler()
    {
    }

    public void Handle(ExampleEvent args)
    {
        //Handle Event
    }
}
鉴于这将失败:

foreach (var domainEvent in entity.DeferredEvents.ToArray())
                {
                    _handler.Raise(domainEvent);
                }
我对我的实体的收藏如下:

public List<IDomainEvent> DeferredEvents { get; set; }
公共列表延迟事件{get;set;}

我仍然不确定如何解决此问题。

此问题是由您调用
\u handler.Raise造成的。正如您所说,
延迟事件
存储在
列表
中。这会导致失败的代码如下所示:

foreach (var domainEvent in entity.DeferredEvents.ToArray())
{
    _handler.Raise<IDomainEvent>(domainEvent);
}
public void Raise<IDomainEvent>(IDomainEvent args) where T : IDomainEvent
{
    foreach (var handler in _container.Resolve<IEnumerable<IHandle<IDomainEvent>>>())
    {
        handler.Handle(args);
    }
}
public void Raise(IDomainEvent args)
{
    foreach (var handler in _container.Resolve<IEnumerable<IHandle<IDomainEvent>>>())
    {
        handler.Handle(args);
    }
}
查看您的注册,没有实现
IHandle
接口的事件处理程序。只有一个实现了
IHandle
接口。因此,调用resolve
IEnumerable
将不会产生任何结果

更新
那么在这种情况下,是否就没有办法通过接口或基类的集合进行循环?在上述假设下,Autofac将基于接口或基类而不是派生类型解析实例,但我在许多域事件示例中都看到了同样的方法

Autofac根据注册进行解析。在您的示例中,
ExampleEventHandler
实现了
IHandle
,并注册为
IHandle
,因此如果解析
IEnumerable
,则不会返回
ExampleEventHandler
的实例

但是,我不认为注册是错误的,我认为错误在于调用
Raise
方法的方式。
Raise
方法有一个未使用的泛型类型参数
T
(至少在您的示例中未使用)。在您的示例中,
Raise
方法实际上如下所示:

foreach (var domainEvent in entity.DeferredEvents.ToArray())
{
    _handler.Raise<IDomainEvent>(domainEvent);
}
public void Raise<IDomainEvent>(IDomainEvent args) where T : IDomainEvent
{
    foreach (var handler in _container.Resolve<IEnumerable<IHandle<IDomainEvent>>>())
    {
        handler.Handle(args);
    }
}
public void Raise(IDomainEvent args)
{
    foreach (var handler in _container.Resolve<IEnumerable<IHandle<IDomainEvent>>>())
    {
        handler.Handle(args);
    }
}
或者,您可以将所有处理程序更改为实现
IHandle>
,如果事件类型与预期类型不匹配,则不执行任何操作:

public class ExampleEventHandler : IHandle<IDomainEvent>
{
    public ExampleEventHandler()
    {
    }

    public void Handle(IDomainEvent args)
    {
        if (!(args is ExampleEvent))
            return;

        //Handle Event
    }
}
公共类ExampleEventHandler:IHandle
{
public ExampleEventHandler()
{
}
公共无效句柄(IDomainEvent参数)
{
如果(!(args是ExampleEvent))
返回;
//处理事件
}
}

那么在这种情况下,是否就没有办法在接口或基类的集合中循环?在上述假设下,Autofac将基于接口或基类而不是派生类型解析实例,但我在许多域事件示例中都看到了同样的方法。
public class ExampleEventHandler : IHandle<IDomainEvent>
{
    public ExampleEventHandler()
    {
    }

    public void Handle(IDomainEvent args)
    {
        if (!(args is ExampleEvent))
            return;

        //Handle Event
    }
}