Autofac 4 Resolve>> 返回一个空列

本文关键字:一个 返回 IEnumerable IEventHandler TEvent Autofac Resolve | 更新日期: 2023-09-27 18:32:44

我已经经历了数十个类似的问题,但没有找到解决问题的方法。因此,这可能是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 4 Resolve<IEnumerable<IEventHandler<TEvent>>> 返回一个空列

在组合根中使用 RegisterGeneric 来注册 IEventHandler<>

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

更新

啊,我现在明白了,你只需要构造正确的类型来传递给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的评论后编辑