1

我正在使用 Autofac 和 MediatR 构建基于 CQRS 的 .Net Core 2.1 应用程序。

public class MediatorModule : Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();

        var mediatrOpenTypes = new[]
        {
            typeof(IRequestHandler<,>),
            typeof(INotificationHandler<>),
        };

        foreach (var mediatrOpenType in mediatrOpenTypes)
        {
            builder
                .RegisterAssemblyTypes(typeof(CreateMessageCommand.GetTypeInfo().Assembly)
                .AsClosedTypesOf(mediatrOpenType)
                .AsImplementedInterfaces();
        }

        builder.RegisterGeneric(typeof(RequestPostProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>));
        builder.RegisterGeneric(typeof(RequestPreProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>));

        builder.Register<ServiceFactory>(ctx =>
        {
            var c = ctx.Resolve<IComponentContext>();
            return t => c.Resolve(t);
        });

    }
}

当我将命令提供给调解器时,它工作得很好,并且命令处理程序上的 Handle() 被执行。

var cmd = new CreateMessageCommand("Foo")
_mediator.Send(cmd)

当我以这种方式执行时,事情并不顺利

var cmd = new CreateMessageCommand("Foo")
var req = new IdentifiedCommand<CreateMessageCommand, bool>(cmd, @event.Id);
await _mediator.Send(req);

例外:

2[Backend.MessageService.Commands.IdentifiedCommand未处理的异常:System.InvalidOperationException:为 MediatR.IRequestHandler 2[Backend.MessageService.Commands.CreateMessageCommand,System.Boolean],System.Boolean]类型的请求构造处理程序时出错。向容器注册您的处理程序。有关示例,请参阅 GitHub 中的示例。---> Autofac.Core.Registration.ComponentNotRegisteredException:请求的服务'MediatR.IRequestHandler2[[Backend.MessageService.Commands.IdentifiedCommand2[[Backend.MessageService.Commands.CreateMessageCommand,Backend.MessageService,版本=1.0.0.0,文化=中性,PublicKeyToken=null],[System.Boolean,System.Private.CoreLib,版本=4.0.0.0,文化=中性, PublicKeyToken=7cec85d7bea7798e]], Backend.MessageService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e ]]' 尚未注册。要避免此异常,请注册一个组件以提供服务,使用 IsRegistered() 检查服务注册,或使用 ResolveOptional() 方法解决可选依赖项。

public class IdentifiedCommand<T, R> : IRequest<R>
    where T : IRequest<R>
{
    public T Command { get; }
    public Guid Id { get; }
    public IdentifiedCommand(T command, Guid id)
    {
        Command = command;
        Id = id;
    }
}

public class IdentifiedCommandHandler<T, R> :
    IRequestHandler<IdentifiedCommand<T, R>, R>
    where T : IRequest<R> {...}

我可以知道缺少什么吗?

4

2 回答 2

3

您发送给 MediatR 的命令类型为IdentifiedCommand<CreateMessageCommand, bool>。因此 MediatR 将寻找类型为 的处理程序IRequestHandler<IdentifiedCommand<CreateMessageCommand, bool>, bool>>

DI 容器通常会首先查找完全匹配,然后考虑开放的泛型类型注册。在这种情况下,它将寻找一个IRequestHandler<,>注册,并为其插入类型参数IdentifiedCommand<CreateMessageCommand, bool>bool。但是,您的命令处理程序没有实现IRequestHandler<T, R>,而是实现IRequestHandler<IdentifiedCommand<T, R>, R>了不适合此的。所以 DI 容器没有找到处理程序并将引发该错误。

为了使其工作,您必须以 DI 容器查找它的方式实现该类型。因此,您将不得不实施IRequestHandler<T, R>

不幸的是,这也意味着您无法以类型安全的方式IdentifiedCommand<T, R>在处理程序中接受 an 。相反,您只会收到一个T您必须处理的请求。

于 2018-09-01T00:57:45.923 回答
2

添加这个解决了我的问题。

builder.RegisterType(typeof(IdentifiedCommandHandler<CreateMessageCommand, bool>))
    .As<IRequestHandler<IdentifiedCommand<CreateMessageCommand, bool>, bool>>()
    .AsImplementedInterfaces();
于 2018-09-01T17:59:42.820 回答