我在 ASP.NET Core 6 中构建了多租户架构,我想创建一个像 MessageService 这样的服务实例,它是应该为每个租户隔离的单例服务。问题是当我进行依赖注入时,有 3 个生命周期范围是
Singleton
Transient
Scope
对于 Transient 和 Scope,它会在每次请求到来时创建新实例,而 Singleton 它将创建 1 次,但它会与所有租户混合
我的问题是如何使用 Autofac 或使用任何其他框架/库在 asp.net core 6 中创建类似于每个租户的 Singleton 的服务实例?或者简而言之:我想在 ASP.NET Core 6 中创建特定于租户的容器。
内置 DI 不支持 keyed dependencies/injection based on name 所以你基本上有两个选择 - 切换到另一个支持它的容器(例如 Autofac - 和 my take on factory with it)或者创建一个工厂。使用
Func
工厂的第二种方法的简单示例如下所示(假设租户对于应用程序运行是静态的,动态可以通过类似的方式进行小的修改):
interface ISomeTenantService
{
public int TenantId { get; } // possibly move to another interface for interface segregation
public void SomeMethod();
}
class SomeTenantServiceParams
{
// all required deps here
}
class SomeTenantService : ISomeTenantService
{
public SomeTenantService(int tenantId, SomeTenantServiceParams p)
{
TenantId = tenantId;
// flatten and assign SomeTenantServiceParams
// ...
}
public int TenantId { get; }
public void SomeMethod()
{
throw new NotImplementedException();
}
}
// registration:
int[] tenants = { 1, 2 }; // supported tenants
services.AddSingleton<SomeTenantServiceParams>();
foreach (var tenantId in tenants)
{
services.AddSingleton<ISomeTenantService>(sp =>
new SomeTenantService(tenantId, sp.GetRequiredService<SomeTenantServiceParams>()));
}
services.AddSingleton<Func<int, ISomeTenantService>>(sp =>
{
var all = sp.GetRequiredService<IEnumerable<ISomeTenantService>>();
var lookup = all.ToDictionary(s => s.TenantId);
return i => lookup[i];
});
然后在需要的地方注入
Func<int, ISomeTenantService>
工厂并简单地使用它:
Func<int, ISomeTenantService> _factory = ...; // injected
var forFirstTenant = _factory(1);