这是使用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需要对启动实例化的处理程序的引用。
有什么想法吗?
答案 0 :(得分:0)
基本上有两种解决方案:
WindowServiceTenant
实例配置所需的值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
,以使解析WindowServiceTenant
和ITenant
都将在单个服务范围内产生相同的实例。这很重要,因为否则将在该作用域实例上设置状态。在同一服务范围内拥有多个实例显然不会产生正确的结果。IServiceScope
上的CreateScope
扩展名方法来开始新的IServiceProvider
。WindowServiceTenant
。您可以解决此具体类型,因为ITenant
抽象将无法设置正确的值(因为这是实现细节)WindowServiceTenant
实例中。由于该实例在服务范围内被重用,因此它将被注入依赖ITenant
的任何已解析对象图中。