在多租户应用程序中解析接口,而无需使用Autofac指定具体类

时间:2015-03-19 14:43:49

标签: c# dependency-injection autofac multi-tenant

我有一个多租户申请。我必须用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();
});

嗯......它完美地工作......它按照我的预期工作 但我不喜欢我必须添加具体的注册类。这意味着我必须在项目中添加一个引用...例如,如果我有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>

此解决方案&#34;工作&#34;但我没有预期的结果,因为Module1和Module2都为两个租户都解决了。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

您可以使用自定义属性标记程序集

[assembly: TenantAttribute("tenant1")]

然后列出所有这些内容并使用RegisterAssemblyModules内的ConfigureTenant方法。

如果您的应用程序在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);
    });
}