我有一个.net核心Web API,我一直在尝试向其添加大众运输消费者。消费者对服务有依赖性。该服务已在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));
}
由于该服务是异步作用域,因此失败。 Simple Injector不喜欢那样。因此,经过一番挖掘,我提出了第二个迭代:
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问题。
有什么想法吗?
答案 0 :(得分:3)
添加对MassTransit.SimpleInjector包的引用,然后在您的接收端点中,使用以下命令配置使用者:
cfg.ReceiveEndpoint("queue_name", e =>
{
e.Consumer<AddMyCommandConsumer>(container);
});
扩展方法将正确配置范围提供程序,并添加使用者工厂以从容器中提取。您的使用者应注册为AsyncScoped,以便其正确处理异步/等待(MT很大程度上建立在TPL上)。
container.Register<AddMyCommandConsumer>(Lifestyle.Scoped);
此外,我认为有一个容器选项可将异步生活方式指定为默认生活方式。
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
希望这会有所帮助,您遇到的任何其他错误都可能与服务或DbContext的注册方式有关。