[英]Masstransit configuring a generic consumer
我正在使用 MassTransit 在我们现有的应用程序中集成消息传递代理。 我们已经实现了一种具有通用实现的命令处理程序,如下所示:
public class MyCommandHandler: CommandHandlerBase<MyCommand>
现在制作一个通用的 Consumer 相对容易,它会做一些样板化并将工作交给准备好的命令处理程序,从 DI 容器请求。
public class CommandConsumer<TCommand> : IConsumer<TCommand>
这样我就可以通过 Microsoft 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
可用时不能直接使用。 我尝试将标记 class CommandConsumer: IConsumer
到CommandConsumer<TCommand>
并制作CommandConsumerDefinition: ConsumerDefinition<CommandConsumer>
,并将上面的内容更改为cfg.AddConsumer(consumerType, typeof(CommandConsumerDefinition));
,但这不起作用,因为永远不会命中 ConfigureConsumer 覆盖。
我应该如何向我在编译时不知道其类型的消费者添加额外的配置?
克里斯的回答让我走上了一个可行的解决方案。 使 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;
}
由于自动发现,我们已经在反射的 realm 中,所以这似乎是一个可以接受的解决方案。 这样我们就可以拥有通用的消费者和定义,而不必为我们拥有的每个命令合约添加新的 class。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.