如何在MassTransit队列消费者中注入Autofac托管的服务?
解决方案
问题根源在于你直接调用Consumer<Consumers>()会绕过依赖注入容器,手动实例化消费者(优先调用无参构造函数),而没有让Autofac来解析带参数的构造函数。按照以下步骤修改即可:
1. 修正MassTransit端点配置
将ReceiveEndpoint中的configureEndpoint.Consumer<Consumers>()替换为configureEndpoint.ConfigureConsumer<Consumers>(context),这个方法会让依赖注入容器(Autofac)来创建消费者实例,自动注入所需的IService:
.ConfigureServices((hostContext, services) => { services.AddMassTransit(cfg => { cfg.AddConsumer<Consumers>(); cfg.UsingRabbitMq((context, cfgss) => { cfgss.Host(new Uri("rabbitmq://localhost/"), hostss => { hostss.Username("guest"); hostss.Password("guest"); }); cfgss.ReceiveEndpoint("Queue_Name", configureEndpoint => { // 替换为ConfigureConsumer,让容器解析消费者 configureEndpoint.ConfigureConsumer<Consumers>(context); }); cfgss.ConfigureEndpoints(context); }); }); })
2. (可选)简化端点配置(推荐)
如果你不需要额外的端点自定义配置,可以去掉手动的ReceiveEndpoint,直接通过AddConsumer指定队列名,让ConfigureEndpoints自动创建端点:
.ConfigureServices((hostContext, services) => { services.AddMassTransit(cfg => { cfg.AddConsumer<Consumers>() .Endpoint(e => e.Name = "Queue_Name"); // 直接指定队列名 cfg.UsingRabbitMq((context, cfgss) => { cfgss.Host(new Uri("rabbitmq://localhost/"), hostss => { hostss.Username("guest"); hostss.Password("guest"); }); cfgss.ConfigureEndpoints(context); // 自动配置所有消费者的端点 }); }); })
3. 确保依赖注册正确
确认你的EventService已经正确注册到Autofac,你的现有代码已经完成这一步,保持即可:
.ConfigureContainer<ContainerBuilder>(builder => { builder.RegisterType<EventService>().As<IService>(); // 可选:如果需要手动注册消费者(通常AddConsumer已自动处理,可省略) // builder.RegisterType<Consumers>().As<IConsumer<Msg>>(); })
关键说明
Consumer<T>()方法会直接实例化T,不会走依赖注入,所以会调用无参构造函数。ConfigureConsumer<T>(context)方法会利用传入的context(服务提供器)来解析T的实例,Autofac会自动找到带IService参数的构造函数并注入依赖。- 确保消费者的带参构造函数是public的(你的代码已经满足),否则容器无法解析。
内容的提问来源于stack exchange,提问作者blu3f1rest0rm
相关产品推荐
相关产品推荐

