如何将Autofac模块与多租户容器一起使用?

时间:2015-04-11 11:25:20

标签: c# autofac multi-tenant autofac-module

如何将Autofac ModulesMultitenant套餐结合使用?

这是Autofac的引导部分:

var builder = new ContainerBuilder();

// only very basic common registrations here... 
// everything else is in modules

// Register the Autofac module for xml configuration as last 
// module to allow (emergency) overrides.
builder.RegisterModule(new ConfigurationSettingsReader());

// create container for IoC
this.container = builder.Build();

// check for tenant strategy -> if exists, go multi-tenant
if (this.container.IsRegistered<ITenantIdentificationStrategy>())
{
    var tenantIdentificationStrategy = this.container
                                           .Resolve<ITenantIdentificationStrategy>();
    this.container = new MultitenantContainer(tenantIdentificationStrategy,
                                              this.container);

    // how to use xml modules instead of manually register at this point?
} 
else 
{ ... }

我不想打电话给

container.ConfigureTenant('1', b => b.RegisterType<Tenant1Dependency>()
                                     .As<IDependency>()
                                     .InstancePerDependency());

在引导程序中(不需要了解这一点)。

相反,我想做这样的事情:

public class TenantModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
         container.ConfigureTenant('1', b => b.RegisterType<Tenant1Dependency>()
                                              .As<IDependency>()
                                              .InstancePerDependency());

         container.ConfigureTenant('2', b => b.RegisterType<Tenant2Dependency>()
                                              .As<IDependency>()
                                              .InstancePerDependency());
         ...

我的第一个想法是检查何时为特殊租户注册:

public class TenantModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.Register((c, p) => {

            var s = c.Resolve<ITenantIdentificationStrategy>();
            if (s != null)
            {
               var id = s.IdentifyTenant<string>();
               ...
            }
        });

我可以检查id并仅在id适合时注册,但如果id不匹配则返回什么?空值? DoNothingObject?对我来说代码看起来很奇怪/可怕

builder.Register("1", (context, parameters) => ...
感觉更自然。但我不知道如何通过Autofac实现这一目标。我错过了什么?你是怎么解决这个问题的?

1 个答案:

答案 0 :(得分:2)

错过了ConfigureTenant也通过了containerBuilder这一点,它允许注册租户特定的ConfigurationSectionReader。因此,可以选择具有额外的客户/租户特定ConfigurationSection:

   mtc.ConfigureTenant("mytenant1",
         containerBuilder =>
         {
             containerBuilder.RegisterModule(new ConfigurationSettingsReader("mytenant1"));
         }
   );

   mtc.ConfigureTenant("mytenant2",
         containerBuilder =>
         {
             containerBuilder.RegisterModule(new ConfigurationSettingsReader("mytenant2"));
         }
   );

这也让我想到我可以先解决租户识别策略,获取标识符并只为当前租户注册(如客户特定的引导程序):

   var tenantIdentificationStrategy = container.Resolve<ITenantIdentificationStrategy>();
   var tid = tenantIdentificationStrategy.IdentifyTenant<string>();

   mtc.ConfigureTenant(tid ,
         containerBuilder =>
         {
             containerBuilder.RegisterModule(new ConfigurationSettingsReader(tid));
             // or something like that which identifies the tenant config section
         }
   );

或者我可以把它变成一个简单的foreach来为所有可用的租户进行注册(但这在大多数情况下都很奇怪,因为只有一个租户会在其引导部分得到解决,也许是其他特殊情况值得的提)。

有更好的想法吗?我会投票赞成更好的想法......; - )