0

我能够让我的命令和查询与它们各自的处理程序一起正常工作,但装饰器却没有。

我正在将 Autofac 与 MediatR 一起使用。一个复杂的问题是我的消息(命令/查询/事件)在一个单独的项目中,因此需要通过 Autofac 的程序集进行注册。

这是我的 CommandHandler 接口:

public interface ICommandHandler<in TCommand, TResponse> : IRequestHandler<TCommand, TResponse> 
    where TCommand : MediatR.IRequest<TResponse>
{
}

一个示例 CommandHandler:

public class AddExternalLoginToUserCommandHandler : CommandHandler<AddExternalLoginToUser, CommonResult>
{
    private readonly UserManager<AppUser> _userManager;

    public AddExternalLoginToUserCommandHandler(
        UserManager<AppUser> userManager, ILogger logger) : base(logger)
    {
        ...
    }

    protected override async Task<CommonResult> HandleImplAsync(
        AddExternalLoginToUser command, CancellationToken cancellationToken)
    {
        ... details deleted...

        return
            new CommonResult(Outcome.Succeeded);
    }
}

我的装饰器:

public class LoggingCommandDecorator<TCommand, TResult> : ICommandHandler<TCommand, TResult> 
    where TCommand : ICommand<TResult>
    where TResult : ICommonResult
{
    private readonly ICommandHandler<TCommand,TResult> _commandHandler;

    public LoggingCommandDecorator(ICommandHandler<TCommand,TResult> commandHandler)
    {
        _commandHandler = commandHandler;
    }

    public async Task<TResult> Handle(TCommand command, CancellationToken cancellationToken)
    {
        Debug.WriteLine("***** HOLY $%1@ IT WORKED ******");

        TResult result = await _commandHandler.Handle(command, cancellationToken);

        return result;
    }
}

还有我的部分配置:

public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // Database, Authentication and Azure config stuff deleted for clarity...

        // AUTOFAC DI/IOC CONFIGURATION

        var builder = new ContainerBuilder();

        // Copies existing dependencies from IServiceCollection
        builder.Populate(services);

        // Enables contravariant Resolve() for interfaces with single contravariant ("in") arg
        builder
            .RegisterSource(new ContravariantRegistrationSource());

        // Mediator itself
        builder
            .RegisterType<Mediator>()
            .As<IMediator>()
            .InstancePerLifetimeScope();

        // Request handlers
        builder
            .Register<SingleInstanceFactory>(ctx => {
                var c = ctx.Resolve<IComponentContext>();
                return t => { object o; return c.TryResolve(t, out o) ? o : null; };
            })
            .InstancePerLifetimeScope();

        // Notification handlers
        builder
            .Register<MultiInstanceFactory>(ctx => {
                var c = ctx.Resolve<IComponentContext>();
                return t => (IEnumerable<object>)c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
            })
            .InstancePerLifetimeScope();

        // Register query handlers
        builder.RegisterAssemblyTypes(typeof(QueryHandler<,>).GetTypeInfo().Assembly).AsImplementedInterfaces(); // via assembly scan

        // REGISTER COMMAND HANDLERS AS KEYED SERVICE

        Assembly commandHandlerAssembly = typeof(CommandHandler<,>).Assembly;

        builder.RegisterAssemblyTypes(commandHandlerAssembly)
            .As(t => t.GetInterfaces()
                .Where(i => i.IsClosedTypeOf(typeof(ICommandHandler<,>)))
                .Select(i => new KeyedService("command-handler", i)))
            .AsImplementedInterfaces();

        // REGISTER DECORATOR

        builder.RegisterGenericDecorator(
            typeof(LoggingCommandDecorator<,>),
            typeof(ICommandHandler<,>),
            fromKey: "command-handler");

        // Finalize
        var container = builder.Build();

        //Create the IServiceProvider based on the container.
        return new AutofacServiceProvider(container);
    }

关于让装饰器处理程序触发的任何想法?如前所述,命令和查询运行良好。

跟进:开放泛型和装配扫描

MediatR Git 页面上有讨论 Autofac、Open Generics 和 Assembly 扫描的困难:

https://github.com/jbogard/MediatR/issues/128

在进行程序集扫描时,Autofac 似乎不支持注册开放的泛型......

我知道这个问题,但在我看来这不是一个因素。我知道程序集扫描和注册是成功的,因为命令处理程序已正确注册。还是我忽略了什么?

4

0 回答 0