Microsoft依赖项注入。我如何才能将数据获取到深度几层的构造函数注入类

时间:2019-03-29 15:42:21

标签: c# dependency-injection .net-core

这是使用Microsoft.Extensions.DependencyInjection的dotNet核心2.2项目。

我有3节课。 A类在构造函数中使用B类。 B类使用C类,而C类使用ITenant接口。

ITenant确定将使用哪个数据库。

示例:

public A(IB b)
public B(IC c)
public C(ITenant t)

它们在注射容器中的设置如下:

services.AddTransient<IA, A>();
services.AddTransient<IB, b>();
services.AddTransient<IC, c>();
services.AddTransient<ITenant , HttpTenant>()>();

在Web项目中,控制器使用Class A作为构造函数参数,并使用容器createClass A及其所有依赖项。 ITenant(HttpTenant)的实现从HTTP请求标头中提取租户名称,并从配置文件中获取数据库信息。一切正常。

现在我需要从Windows服务调用此服务,该服务不涉及HTTP请求。我有一个响应消息队列的处理程序,并且A类是构造参数。对于Windows服务,我有一个不同的ITenant(WindowServiceTenant):

services.AddTransient<ITenant , WindowServiceTenant>()>();

我不知道如何将租户代码放入WindowServiceTenant。

  • 在运行时根据从消息队列读取的值确定租户。
  • 在我的处理程序实例化时,WindowServiceTenant也被实例化。
  • 在处理程序恢复之前,我不知道租户。

我需要获取WindowServiceTenant实例的引用并提供租户。或者,此实现WindowServiceTenant需要对启动实例化的处理程序的引用。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

基本上有两种解决方案:

  1. 在解析处理程序之前,为WindowServiceTenant实例配置所需的值
  2. 通过环境状态传达该值,例如,可用于线程(ThreadLocal<T>)或异步操作(AsyncLocal<T>)的值

第一个选项要求将WindowServiceTenant注册为Scoped服务并创建IServiceScope,从中您可以解析WindowServiceTenant和适当的处理程序:< / p>

// Registration
services.AddScoped<WindowServiceTenant>();
services.AddScoped<ITenant>(c => c.GetRequiredService<WindowServiceTenant>());

// Usage
using (var scope = serviceProvider.CreateScope())
{
    var services = serviceScope.ServiceProvider;

    var tenant = services.GetRequiredService<WindowServiceTenant>();

    // Set the right tenant based on a value from the queue
    tenant.SetTenantValue(...);

    // Resolve and execute handler
    var handler = services.GetRequiredService(handlerType);
}

上一个代码清单执行以下操作:

  • 它通过其具体类型和接口来注册WindowServiceTenant,以使解析WindowServiceTenantITenant都将在单个服务范围内产生相同的实例。这很重要,因为否则将在该作用域实例上设置状态。在同一服务范围内拥有多个实例显然不会产生正确的结果。
  • 处理完邮件后,您可以使用IServiceScope上的CreateScope扩展名方法来开始新的IServiceProvider
  • 在此范围内,您解决WindowServiceTenant。您可以解决此具体类型,因为ITenant抽象将无法设置正确的值(因为这是实现细节)
  • 您将队列中的租户值存储在WindowServiceTenant实例中。由于该实例在服务范围内被重用,因此它将被注入依赖ITenant的任何已解析对象图中。