Masstransit配置通用消费者

问题描述 投票:0回答:1

我正在使用MassTransit.We已经实现了一种命令处理程序,它有通用的实现,像这样。

public class MyCommandHandler: CommandHandlerBase<MyCommand>

现在做一个通用的Consumer相对容易一些,它可以做一些锅炉电镀,并将工作交给准备好的命令处理程序,从DI容器中请求。

public class CommandConsumer<TCommand> : IConsumer<TCommand>

然后,我可以很容易地通过微软DI注册。

cfg.AddConsumer<CommandConsumer<MyCommand>>(x => some configuration...);

这一切都很好,所以我继续下一步, 即提取消费者注册到一个通用的帮助方法, 这是我有点困惑的地方。这个方法(目前)看起来有点像这样。

public static IServiceCollection ConfigureMassTransit(this IServiceCollection services, params Type[] consumerTypes)
{
        return 
            services.AddMassTransit(cfg =>
            {
                foreach (var consumerType in consumerTypes)
                {
                    cfg.AddConsumer(consumerType);
                }
                // or cfg.AddConsumers(consumerTypes);
                cfg.AddBus(context => Bus.Factory.CreateUsingRabbitMq(config =>
                {
                    var host = config.Host("localhost", "/",
                        h =>
                        {
                            h.Username("guest");
                            h.Password("guest");
                        });
                    config.ConfigureEndpoints(context);
                }));

            });
    }

谓之 services.ConfigureMassTransit(typeof(CommandConsumer<MyCommand>));这又可以了,但我想不通的是,如何在注册时增加额外的配置;采取Action的超载只有在使用通用签名时才可以使用,当你只有 Type 可用。我试着添加一个标记类 CommandConsumer: IConsumerCommandConsumer<TCommand> 并使 CommandConsumerDefinition : ConsumerDefinition<CommandConsumer>并将上述内容改为 cfg.AddConsumer(consumerType, typeof(CommandConsumerDefinition));但这并不奏效,因为ConfigureConsumer覆盖从未被击中。

我应该如何为一个在编译时不知道类型的消费者添加附加配置?

c# dependency-injection masstransit
1个回答
0
投票

Chris的回答让我走上了工作解决方案的道路。使CommandConsumerDefinition通用,使我能够在运行时使用反射以相同的方式构造这两个类型。这使得MassTransit能够以预期的方式连接配置。

最后,我还使用了一个 "标记 "属性,它将保存命令合同的类型,因此它们可以被发现,而不必在启动时作为参数输入。

public static IServiceCollectionConfigurator ConfigureMassTransitConsumers(this IServiceCollectionConfigurator serviceConfigurator, Assembly assembly)
    {
        foreach (var type in assembly.GetTypes())
        {
            var attributes = type.GetCustomAttributes(typeof(RegisterCommandConsumerAttribute), false);
            if (attributes.Length <= 0) continue;
            foreach (var attribute in attributes)
            {
                if (attribute is RegisterCommandConsumerAttribute registerCommandConsumerAttribute)
                {
                    Type consumerType = typeof(CommandConsumer<>).MakeGenericType(registerCommandConsumerAttribute.CommandType);
                    Type consumerDefinitionType = typeof(CommandConsumerDefinition<>).MakeGenericType(registerCommandConsumerAttribute.CommandType);
                    serviceConfigurator.AddConsumer(consumerType, consumerDefinitionType);
                }
            }
        }
        return serviceConfigurator;
    }

因为自动发现,我们已经进入了反思的领域,所以这似乎是一个可以接受的解决方案。这样我们就可以拥有通用的消费者和定义,而不必为我们的每一个命令合同添加一个新的类。

© www.soinside.com 2019 - 2024. All rights reserved.