C# 公共交通消费者和简单喷射器的DI困境

C# 公共交通消费者和简单喷射器的DI困境,c#,dependency-injection,.net-core,simple-injector,masstransit,C#,Dependency Injection,.net Core,Simple Injector,Masstransit,我有一个.net核心web api,我一直在尝试添加一个公共交通消费者。消费者对服务有依赖性。该服务已在简单注入器容器中注册 container.Register<IMyService, MyService>(Lifestyle.Scoped); 所以我的下一步是设置终点。首先,请这样做: cfg.ReceiveEndpoint(host, options.MyQueue, e => { var service = container.GetService<I

我有一个.net核心web api,我一直在尝试添加一个公共交通消费者。消费者对服务有依赖性。该服务已在简单注入器容器中注册

container.Register<IMyService, MyService>(Lifestyle.Scoped); 
所以我的下一步是设置终点。首先,请这样做:

cfg.ReceiveEndpoint(host, options.MyQueue, e =>
{
    var service = container.GetService<IMyService>();
    e.Consumer(() => new AddMyCommandConsumer(service));
}
cfg.ReceiveEndpoint(主机,options.MyQueue,e=>
{
var service=container.GetService();
e、 消费者(()=>newaddmycommandconsumer(服务));
}
由于服务的作用域是异步的,所以失败了。Simple Injector不喜欢这样。因此,经过一番挖掘,我提出了第二次迭代:

cfg.ReceiveEndpoint(host, options.MyQueue, e =>
{
    using (AsyncScopedLifestyle.BeginScope(container))
    {
        var service = container.GetService<IMyService>();
        e.Consumer(() => new AddMyCommandConsumer(service));
    }
}
cfg.ReceiveEndpoint(主机,options.MyQueue,e=>
{
使用(AsyncScopedLifestyle.BeginScope(容器))
{
var service=container.GetService();
e、 消费者(()=>newaddmycommandconsumer(服务));
}
}
这个get更进一步,创建了使用者,调用了consume方法,但是一旦我使用了服务并且需要DBContext,simple injector就会抱怨DBContext已经被释放。如果我使用删除了语句,那么它可以工作,但是范围永远不会被释放

然后,我查看了MassTransit.SimpleInjector nuget包。我找不到任何文档和示例,但经过一番挖掘,我得出了以下结论:

var consumerFactory = new ScopeConsumerFactory<AddMyCommandConsumer>(new 
    SimpleInjectorConsumerScopeProvider(container));                        
e.Consumer(consumerFactory);
var consumerFactory=new ScopeConsumerFactory(新建)
SimpleInjectorConsumerScopeProvider(容器));
e、 消费者(消费者工厂);
Mass Transit试图创建消费者,但这次失败了,因为Simple Injector无法创建服务,即使它已在容器中注册。最后一次尝试只是一点猜测,正如我上面所说,没有文档或示例。老实说,我认为,即使我成功,我也会遇到同样的问题使用如上所述的DBContext的lem


有什么想法吗?

添加对MassTransit.SimpleInjector包的引用,然后在接收端点中,使用以下命令配置使用者:

cfg.ReceiveEndpoint("queue_name", e =>
{
    e.Consumer<AddMyCommandConsumer>(container);
});

希望这会有所帮助,您得到的任何其他错误都可能与您的服务或DbContext的注册方式有关。

您可以在单元测试中找到使用示例:--遗憾的是,提供扩展包的开发人员从未将页面添加到docsI,不会将其添加为ana应答,但说真的,.NET Core已经有了一个可用的服务定位器。总的来说,我个人更喜欢使用复合根目录,但MS DI很好,你无论如何都必须使用它。使用两个容器,一个在另一个之上有什么意义?Alexey,我认为你可能100%正确。就在你刚开始使用.net core的时候,文档和各种博客帖子下意识地建议使用Microsoft应该更换DI容器。事后看来,我认为您可能不需要。“您的消费者应该注册为AsyncScope”。使用者是否在单个作用域内重复使用或多次请求?否则,默认的瞬态生活方式将很好。将根类型注册为作用域通常只会使配置复杂化。是的,这是一个干净的解决方案。我的使用者不会被容器或异步相关代码阻塞,容器看起来更安全r注入所需的一切。使用者必须是异步作用域,因为服务是异步作用域(因此它依赖于存储库)。它们可以并且在一个作用域内多次使用,因此我认为异步作用域是可行的。如果服务是异步作用域,则使用者也必须是。同意@Steven的说法,如果将其设置为作用域,则将强制使所有使用者依赖项也设置为作用域。@Alexander在v5中事实上不再是这种情况。在v5中,您现在可以使用ject瞬态进入作用域组件,但没有得到生活方式不匹配警告。@Steven很高兴知道v5终于退出了!但我想规则应该是一样的-将所有内容注册为瞬态,除非需要对其进行作用域或单例。与消费者一样,看起来他们每封消息调用一次。
var consumerFactory = new ScopeConsumerFactory<AddMyCommandConsumer>(new 
    SimpleInjectorConsumerScopeProvider(container));                        
e.Consumer(consumerFactory);
cfg.ReceiveEndpoint("queue_name", e =>
{
    e.Consumer<AddMyCommandConsumer>(container);
});
container.Register<AddMyCommandConsumer>(Lifestyle.Scoped);
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();