将MassTransit抽象到类库:跨项目添加消费者的实现疑问
解决MassTransit类库添加外部项目消费者的方案
下面给你三种可行的实现方式,完全不用让类库反向引用Worker或Web项目:
1. 给CreateBus方法添加自定义配置委托
直接在类库的RabbitMQBusFactory里给CreateBus加一个委托参数,让调用方(Worker/Web项目)自己传入消费者的注册逻辑。
修改后的类库代码:
public class RabbitMQBusFactory { public static IBusControl CreateBus( string rabbitMQUrl, string rabbitMQUser, string rabbitMQPassword, // 新增委托参数,允许外部项目自定义总线配置 Action<IRabbitMqBusFactoryConfigurator, IRabbitMqHost> configureBus = null) { var busControl = Bus.Factory.CreateUsingRabbitMq(cfg => { var host = cfg.Host(new Uri(rabbitMQUrl), hostConfig => { hostConfig.Username(rabbitMQUser); hostConfig.Password(rabbitMQPassword); }); // 执行类库默认的端点配置 cfg.ConfigureEndpoints(host); // 如果外部传入了配置逻辑,执行它(注册消费者等操作) configureBus?.Invoke(cfg, host); }); return busControl; } }
Worker/Web项目里的调用示例:
// 假设Worker项目中有MyMessageConsumer消费者类 var bus = RabbitMQBusFactory.CreateBus( "rabbitmq://localhost", "guest", "guest", (cfg, host) => { // 注册当前项目的消费者到总线 cfg.ReceiveEndpoint(host, "my-message-queue", e => { e.Consumer<MyMessageConsumer>(); }); });
2. 通过程序集扫描自动加载消费者
如果消费者类都实现了IConsumer接口,可以让类库扫描指定程序集,自动注册里面的所有消费者。
修改类库的CreateBus方法,支持传入包含消费者的程序集:
public class RabbitMQBusFactory { public static IBusControl CreateBus( string rabbitMQUrl, string rabbitMQUser, string rabbitMQPassword, params Assembly[] consumerAssemblies) { var busControl = Bus.Factory.CreateUsingRabbitMq(cfg => { var host = cfg.Host(new Uri(rabbitMQUrl), hostConfig => { hostConfig.Username(rabbitMQUser); hostConfig.Password(rabbitMQPassword); }); cfg.ConfigureEndpoints(host); // 遍历传入的程序集,自动扫描并注册所有消费者 foreach (var assembly in consumerAssemblies) { // 直接注册消费者 cfg.Consumer(assembly); // 或者用约定式端点配置,自动生成队列名称 cfg.ConfigureEndpoints(host, new KebabCaseEndpointNameFormatter(), x => { x.IncludeNamespace = false; x.AddConsumers(assembly); }); } }); return busControl; } }
Worker项目调用示例:
// 传入当前项目的程序集,类库会自动扫描里面的消费者 var bus = RabbitMQBusFactory.CreateBus( "rabbitmq://localhost", "guest", "guest", typeof(MyMessageConsumer).Assembly);
3. 结合依赖注入扩展(适合使用DI的场景)
如果你的项目用了依赖注入,可以在类库中提供DI扩展方法,让调用项目先把消费者注册到DI容器,再通过DI完成总线配置。
类库中添加DI扩展:
public static class MassTransitDependencyInjectionExtensions { public static IServiceCollection AddRabbitMQBus( this IServiceCollection services, string rabbitMQUrl, string rabbitMQUser, string rabbitMQPassword) { services.AddMassTransit(config => { // 类库这里不注册消费者,留待调用项目自行添加 config.UsingRabbitMq((ctx, cfg) => { cfg.Host(new Uri(rabbitMQUrl), h => { h.Username(rabbitMQUser); h.Password(rabbitMQPassword); }); cfg.ConfigureEndpoints(ctx); }); }); return services; } }
Worker项目的Program.cs里注册示例:
var builder = Host.CreateDefaultBuilder(args); builder.ConfigureServices(services => { // 先调用类库的DI扩展配置总线基础信息 services.AddRabbitMQBus( "rabbitmq://localhost", "guest", "guest"); // 注册当前项目的消费者到DI容器 services.AddMassTransit(config => { config.AddConsumer<MyMessageConsumer>(); }); });
内容的提问来源于stack exchange,提问作者user24503
相关产品推荐
相关产品推荐

