DI困扰着大众运输用户和简单喷射器

时间:2019-02-13 21:26:12

标签: c# dependency-injection .net-core simple-injector masstransit

我有一个.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问题。

有什么想法吗?

1 个答案:

答案 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的注册方式有关。