Autofac 4 Resolve <ienumerable <ieventhandler <tevent>&gt;&gt;返回一个空列表

时间:2016-02-01 20:06:43

标签: c# event-handling autofac

我在没有找到解决问题的方法的情况下经历了数十个类似的问题。 因此,它可能是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);
        }
    }
}

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

2 个答案:

答案 0 :(得分:0)

<强>更新

我现在明白了,你只需构造正确的类型传递给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

这对我有用,具有以下设置 - 事件界面&amp;类:

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的评论之后编辑

答案 1 :(得分:0)

在Composition Root中使用RegisterGeneric注册IEventHandler&lt;&gt;

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