繁体   English   中英

Autofac 4解决 <IEnumerable<IEventHandler<TEvent> &gt;&gt;返回一个空列表

[英]Autofac 4 Resolve<IEnumerable<IEventHandler<TEvent>>> returns an empty list

我经历过数十个类似的问题,但没有找到解决问题的方法。 因此,Autofac 4可能是一个问题,我发现的所有问题都与以前的版本有关。

我有以下活动的发布者

public class EventPublisher : IEventPublisher
{
    private readonly IComponentContext _context;

    public EventPublisher(IComponentContext context)
    {
        _context = context;
    }

    public async Task Publish<TEvent>(TEvent @event) where TEvent : IEvent
    {
        if (@event == null)
        {
            throw new ArgumentNullException(nameof(@event));
        }

        var eventHandlers = _context.Resolve<IEnumerable<IEventHandler<TEvent>>>();

        foreach (IEventHandler<TEvent> handler in eventHandlers)
        {
            await handler.Handle(@event);
        }
    }
}

这是服务注册

builder.RegisterAssemblyTypes(typeof(SiteEventsHandler).Assembly).AsClosedTypesOf(typeof(IEventHandler<>));

尽管服务已正确注册(我可以在注册表中看到它们),但是resolve方法返回一个空列表。

更新

以下是调用事件发布者的命令发送者

public class CommandSender : ICommandSender
{
    private readonly IResolver _resolver;
    private readonly IEventPublisher _eventPublisher;

    public CommandSender(IResolver resolver, IEventPublisher eventPublisher)
    {
        _resolver = resolver;
        _eventPublisher = eventPublisher;
    }

    public void Send<TCommand>(TCommand command) where TCommand : ICommand
    {
        if (command == null)
        {
            throw new ArgumentNullException(nameof(command));
        }

        var commandHandler = _resolver.Resolve<ICommandHandler<TCommand>>();

        if (commandHandler == null)
        {
            throw new Exception($"No handler found for command '{command.GetType().FullName}'");
        }

        var events = commandHandler.Handle(command);

        foreach (var @event in events)
        {
            _eventPublisher.Publish(@event);
        }
    }
}

命令处理程序返回必须发布的域事件的列表。

更新资料

啊,我现在明白了,您只需要构造正确的类型即可传递给Autofac。 在您的EventPublisher类中尝试以下操作:

public async Task Publish<TEvent>(TEvent @event) where TEvent : IEvent
{
    if (@event == null)
    {
        throw new ArgumentNullException(nameof(@event));
    }

    var handlerType = typeof (IEventHandler<>).MakeGenericType(@event.GetType());
    var handlerCollectionType = typeof (IEnumerable<>).MakeGenericType(handlerType);
    var eventHandlers = _context.Resolve(handlerCollectionType);

    foreach (IEventHandler<TEvent> handler in eventHandlers)
    {
        await handler.Handle(@event);
    }
}

结束更新

您确定服务注册正确吗? 您注册的程序集可能不正确:

typeof(SiteEventsHandler).Assembly

这对我来说适用于以下设置-事件接口和类:

public interface IEvent {}
public class MyEvent : IEvent {}

服务接口:

public interface IEventHandler<in T> where T : Event {}

还有两个实现:

public class MyEventHandlerOne : IEventHandler<MyEvent> {}
public class MyEventHandlerTwo : IEventHandler<MyEvent> {}

Autofac的配置如下:

var builder = new ContainerBuilder();
builder
    .RegisterAssemblyTypes(typeof (IEvent).Assembly)
    .AsClosedTypesOf(typeof (IEventHandler<>))
    .AsImplementedInterfaces()
    .InstancePerDependency();
_container = builder.Build();

解决这些服务将产生以下2个集合:

var canResolve = CanResolve<MyEvent>(_container);

static bool CanResolve<T>(IComponentContext context) where T : IEvent
{
    var handlers = context.Resolve<IEnumerable<IEventHandler<T>>>().ToList();
    return handlers.Any();
}

在34gl3评论后编辑

在您的合成根目录中使用RegisterGeneric来注册IEventHandler <>

http://docs.autofac.org/en/latest/register/registration.html#open-generic-components

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM