使用 Autofac 在不指定具体 class 的情况下解析多租户应用程序中的接口
Resolve an Interface in a multitenant app without specify concrete class with Autofac
我有一个多租户应用程序。我必须用 Autofac 解析一个类型。我能做到……其实并不难。这是我的做法:
第一个解决方案
var tenantIdentifier = new TenantIdentificationStrategy();
var mtc = new MultitenantContainer(tenantIdentifier, container);
mtc.ConfigureTenant("1", t =>
{
t.RegisterType<MultiTenant.ModuleModule1>()
.As<MultiTenant.IModule>();
t.RegisterType<MultiTenant.Controllers.Tenant.Tenant1Controller>()
.As<MultiTenant.Controllers.CommonController>()
.PropertiesAutowired();
});
mtc.ConfigureTenant("2", t =>
{
t.RegisterType<MultiTenant.ModuleModule2>()
.As<MultiTenant.IModule>();
t.RegisterType<MultiTenant.Controllers.Tenant.Tenant2Controller>()
.As<MultiTenant.Controllers.CommonController>()
.PropertiesAutowired();
});
嗯...它完美地工作...它按我预期的那样工作
但我不喜欢我必须添加具体的 class 才能注册。这意味着我必须在项目中添加一个引用...并且,例如,如果我有 10 个不同的租户,我必须在我的项目中添加 10 个引用。
但是我不太喜欢这种情况。
第二种解决方案
我试过这样解决:
mtc.ConfigureTenant("1", t =>
{
t.RegisterType<MultiTenant.Controllers.Tenant.Tenant1Controller>()
.As<MultiTenant.Controllers.CommonController>()
.PropertiesAutowired();
});
mtc.ConfigureTenant("2", t =>
{
t.RegisterType<MultiTenant.Controllers.Tenant.Tenant2Controller>()
.As<MultiTenant.Controllers.CommonController>()
.PropertiesAutowired();
});
并且在网络配置中:
<autofac>
<components>
<component type="MultiTenant.Module1, MultiTenant.Module" service="MultiTenant.IModule, MultiTenant.IModule"></component>
<component type="MultiTenant.Module2, MultiTenant.Module" service="MultiTenant.IModule, MultiTenant.IModule"></component>
</components>
</autofac>
这个解决方案 "works" 但我没有得到预期的结果,因为 Module1 和 Module2 都为两个租户解决了。
我该如何解决这个问题?
您可以使用自定义属性标记程序集
[assembly: TenantAttribute("tenant1")]
然后列出所有这些并在 ConfigureTenant
中使用 RegisterAssemblyModules
方法。
如果您的应用程序 运行 在 IIS
下,我建议使用 BuildManager
列出您的程序集(请参阅 Why aren’t my assemblies getting scanned after IIS restart? 了解说明)。
你可以这样做:
IEnumerable<Assembly> referencedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
if (HostingEnvironment.InClientBuildManager)
{
referencedAssemblies = referencedAssemblies
.Union(BuildManager
.GetReferencedAssemblies()
.Cast<Assembly>())
.Distinct();
}
var groupedAssemblies = referencedAssemblies.Select(ass => new
{
Assembly = ass,
TenantAttribute = ass.GetCustomAttribute<TenantAttribute>()
})
.Where(o => o.TenantAttribute != null)
.GroupBy(o => o.TenantAttribute.TenantId, o => o.Assembly);
foreach (var group in groupedAssemblies)
{
mtc.ConfigureTenant(group.Key, cb =>
{
cb.RegisterAssemblyModule(group);
});
}
我有一个多租户应用程序。我必须用 Autofac 解析一个类型。我能做到……其实并不难。这是我的做法:
第一个解决方案
var tenantIdentifier = new TenantIdentificationStrategy();
var mtc = new MultitenantContainer(tenantIdentifier, container);
mtc.ConfigureTenant("1", t =>
{
t.RegisterType<MultiTenant.ModuleModule1>()
.As<MultiTenant.IModule>();
t.RegisterType<MultiTenant.Controllers.Tenant.Tenant1Controller>()
.As<MultiTenant.Controllers.CommonController>()
.PropertiesAutowired();
});
mtc.ConfigureTenant("2", t =>
{
t.RegisterType<MultiTenant.ModuleModule2>()
.As<MultiTenant.IModule>();
t.RegisterType<MultiTenant.Controllers.Tenant.Tenant2Controller>()
.As<MultiTenant.Controllers.CommonController>()
.PropertiesAutowired();
});
嗯...它完美地工作...它按我预期的那样工作 但我不喜欢我必须添加具体的 class 才能注册。这意味着我必须在项目中添加一个引用...并且,例如,如果我有 10 个不同的租户,我必须在我的项目中添加 10 个引用。 但是我不太喜欢这种情况。
第二种解决方案
我试过这样解决:
mtc.ConfigureTenant("1", t =>
{
t.RegisterType<MultiTenant.Controllers.Tenant.Tenant1Controller>()
.As<MultiTenant.Controllers.CommonController>()
.PropertiesAutowired();
});
mtc.ConfigureTenant("2", t =>
{
t.RegisterType<MultiTenant.Controllers.Tenant.Tenant2Controller>()
.As<MultiTenant.Controllers.CommonController>()
.PropertiesAutowired();
});
并且在网络配置中:
<autofac>
<components>
<component type="MultiTenant.Module1, MultiTenant.Module" service="MultiTenant.IModule, MultiTenant.IModule"></component>
<component type="MultiTenant.Module2, MultiTenant.Module" service="MultiTenant.IModule, MultiTenant.IModule"></component>
</components>
</autofac>
这个解决方案 "works" 但我没有得到预期的结果,因为 Module1 和 Module2 都为两个租户解决了。
我该如何解决这个问题?
您可以使用自定义属性标记程序集
[assembly: TenantAttribute("tenant1")]
然后列出所有这些并在 ConfigureTenant
中使用 RegisterAssemblyModules
方法。
如果您的应用程序 运行 在 IIS
下,我建议使用 BuildManager
列出您的程序集(请参阅 Why aren’t my assemblies getting scanned after IIS restart? 了解说明)。
你可以这样做:
IEnumerable<Assembly> referencedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
if (HostingEnvironment.InClientBuildManager)
{
referencedAssemblies = referencedAssemblies
.Union(BuildManager
.GetReferencedAssemblies()
.Cast<Assembly>())
.Distinct();
}
var groupedAssemblies = referencedAssemblies.Select(ass => new
{
Assembly = ass,
TenantAttribute = ass.GetCustomAttribute<TenantAttribute>()
})
.Where(o => o.TenantAttribute != null)
.GroupBy(o => o.TenantAttribute.TenantId, o => o.Assembly);
foreach (var group in groupedAssemblies)
{
mtc.ConfigureTenant(group.Key, cb =>
{
cb.RegisterAssemblyModule(group);
});
}