我正在使用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);
});
}
}
当我将命令提供给mediator时,它完全正常,并且命令处理程序上的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);
例外:
未处理的异常:System.InvalidOperationException:为类型为MediatR.IRequestHandler
2[Backend.MessageService.Commands.IdentifiedCommand
2 [Backend.MessageService.Commands.CreateMessageCommand,System.Boolean],System.Boolean]的请求构造处理程序时出错。在容器中注册处理程序。有关示例,请参阅GitHub中的示例。 ---> Autofac.Core.Registration.ComponentNotRegisteredException:请求的服务'MediatR.IRequestHandler2[[Backend.MessageService.Commands.IdentifiedCommand
2 [[Backend.MessageService.Commands.CreateMessageCommand,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]],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> {...}
我可以知道缺少什么吗?
您发送给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>
。相反,你只需要一个T
请求,你将不得不与之合作。
添加此解决了我的问题。
builder.RegisterType(typeof(IdentifiedCommandHandler<CreateMessageCommand, bool>))
.As<IRequestHandler<IdentifiedCommand<CreateMessageCommand, bool>, bool>>()
.AsImplementedInterfaces();