我有一个.net核心web api,我一直试图添加一个Mass Transit消费者。消费者依赖于服务。该服务已在Simple Injector容器中注册。
container.Register<IMyService, MyService>(Lifestyle.Scoped);
该服务依次依赖于使用IServiceCollection.AddDbContext添加的DBContext,然后交叉连接:
Container.CrossWire<MyDbContext>(app);
我已将服务添加到消费者的构造函数中,如下所示:
public AddMyCommandConsumer(IMyService service)
{
_service = service;
}
所以我的下一步是设置终点。首先尝试这个:
cfg.ReceiveEndpoint(host, options.MyQueue, e =>
{
var service = container.GetService<IMyService>();
e.Consumer(() => new AddMyCommandConsumer(service));
}
由于服务是异步作用域,因此失败。简单的注射器不喜欢那样。经过一番挖掘后,我想出了第二次迭代:
cfg.ReceiveEndpoint(host, options.MyQueue, e =>
{
using (AsyncScopedLifestyle.BeginScope(container))
{
var service = container.GetService<IMyService>();
e.Consumer(() => new AddMyCommandConsumer(service));
}
}
在创建消费者并调用consume方法时,这会更进一步,但是一旦我需要使用该服务并且需要DBContext,简单的注入器就会抱怨已经处理了DBContext。如果我删除using语句然后它可以工作,但范围从未被处理。
然后我看了一下MassTransit.SimpleInjector nuget包。没有文档也没有我能找到的例子,但经过一番挖掘后我想出了这个:
var consumerFactory = new ScopeConsumerFactory<AddMyCommandConsumer>(new
SimpleInjectorConsumerScopeProvider(container));
e.Consumer(consumerFactory);
Mass Transit尝试创建消费者,但这次失败,因为Simple Injector无法创建服务,即使它已在容器中注册。如上所述,最后一次尝试有点猜测,没有文档或示例。说实话,我认为即使我有这个工作,我最终会遇到与上面的DBContext相同的问题。
有任何想法吗?
添加对MassTransit.SimpleInjector包的引用,然后在接收端点中,使用以下命令配置使用者:
cfg.ReceiveEndpoint("queue_name", e =>
{
e.Consumer<AddMyCommandConsumer>(container);
});
扩展方法将正确配置范围提供程序并添加使用者工厂以从容器中提取。您的消费者应该注册为AsyncScoped,以便它正确处理async / await(MT主要依赖于TPL)。
container.Register<AddMyCommandConsumer>(Lifestyle.Scoped);
另外,我认为有一个容器选项可以指定异步生活方式作为默认值。
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
希望这会有所帮助,您获得的任何其他错误可能与您的服务或DbContext的注册方式有关。