【问题标题】:How to correctly configure InstancePerTenant using Autofac?如何使用 Autofac 正确配置 InstancePerTenant?
【发布时间】:2019-11-15 21:13:59
【问题描述】:

我一直在尝试使用InstancePerTenant 为每个租户设置我的组件实例。然而,InstancePerTenant 在某种程度上表现得像SingleInstance。我的设置有问题吗?

我有这个 ContainerBuilder 扩展,它配置了多租户相关的依赖项。

public static ContainerBuilder AddMultitenancy(this ContainerBuilder builder)
{
  builder.RegisterType<HttpContextAccessor>().As<IHttpContextAccessor>().SingleInstance();
  builder.RegisterType<TenantStore>().As<ITenantStore>().SingleInstance();
  builder.RegisterType<TenantResolverStrategy>().As<ITenantIdentificationStrategy>().SingleInstance();
  return builder
}

租户由主机名标识:

public class TenantResolverStrategy : ITenantIdentificationStrategy
{
  private readonly IHttpContextAccessor httpContextAccessor;

  public TenantResolverStrategy(
    IHttpContextAccessor httpContextAccessor
  )
  {
    this.httpContextAccessor = httpContextAccessor;
  }

  public bool TryIdentifyTenant(out object tenantId)
  {
    // hostname is the tenantId
    tenantId = httpContextAccessor.HttpContext?.Request?.Host.Value;
    return (tenantId != null || tenantId == (object)"");
  }
}

TenantStore 只是一个根据tenantId(主机名)从数据库中解析租户实体的类

public class TenantStore : ITenantStore
{
  private readonly ITenantIdentificationStrategy tenantIdentificationStrategy;
  private readonly MemoryCacheStore cacheStore;
  private readonly ITenantService tenantService;

  public TenantStore(
    ITenantIdentificationStrategy tenantIdentificationStrategy,
    MemoryCacheStore cacheStore,
    ITenantService tenantService
  )
  {
    this.tenantIdentificationStrategy = tenantIdentificationStrategy;
    this.cacheStore = cacheStore;
    this.tenantService = tenantService;
  }

  public async Task<TenantEntity> GetTenantAsync(object tenantId)
  {
    var hostName = (string)tenantId;
    var tenant = cacheStore.Get<TenantEntity>(CacheType.Tenant, hostName);

    if (tenant == null)
    {
      tenant = await tenantService.GetTenantByHostNameFromDatabaseAsync(hostName);
      cacheStore.Set(tenant, CacheType.Tenant, hostName);
    }

    return tenant ?? new TenantEntity();
  }
}

在 Startup.cs 中,我正在向 InstancePerTenant 注册 TenantSpecific

public void ConfigureContainer(ContainerBuilder builder)
{
  builder.AddMultitenancy();
  builder.RegisterType<TenantSpecific>().As<ITenantSpecific>().InstancePerTenant();
}

public static MultitenantContainer ConfigureMultitenantContainer(IContainer container
{
  var strategy = container.Resolve<ITenantIdentificationStrategy>();
  var multitenantContainer = new MultitenantContainer(strategy, container);
  // Nothing important here
  multitenantContainer.RegisterMultitenantSpecificStuff();
  return multitenantContainer;
}

TenantSpecific.cs 和 TenantSpecificController.cs:

public class TenantSpecific
{
  public Guid Id { get; set; }

  public TenantSpecific()
  {
    this.Id = Guid.NewGuid();
  }
}

public class TenantSpecificController : ApiController
{
  private readonly ITenantSpecific tenantSpecific;

  public TenantSpecificController(ITenantSpecific tenantSpecific)
  {
    this.tenantSpecific = tenantSpecific;
  }

  [HttpGet]
  public IActionResult Get()
  {
    return Ok(tenantSpecific.Id);
  }
}

在 Program.cs 中

public static IHostBuilder CreateHostBuilder(string[] args)
{
  var host = Host.CreateDefaultBuilder(args)
    .UseServiceProviderFactory(new AutofacMultitenantServiceProviderFactory(Startup.ConfigureMultitenantContainer))
    .ConfigureWebHostDefaults(webHostBuilder =>
    {
      webHostBuilder
        .UseConfiguration(ConfigurationModule.GetConfiguration())
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>();
    });
  return host;
}

当我调用http://tenant1.localhost/tenant-specific/http://tenant2.localhost/tenant-specific 时,TenantSpecific 的构造函数只像 Singleton 一样被调用一次。 tenantSpecific.Id 返回相同的值。所以我假设InstancePerTenant 在这里不起作用。

我的设置有问题吗?

【问题讨论】:

    标签: c# autofac asp.net-core-3.0


    【解决方案1】:

    如文档中所述ASP.net core multitenant support

    您应该添加对AddAutofacMultitenantRequestServices() 的调用,以将所需的中间件添加到多租户工作所需的根容器中。

    public void ConfigureServices(IServiceCollection services)
    {
        // This will all go in the ROOT CONTAINER and is NOT TENANT SPECIFIC.
        services.AddMvc();
        services.AddControllers();
    
        // This adds the required middleware to the ROOT CONTAINER and 
        // is required for multitenancy to work.
        services.AddAutofacMultitenantRequestServices();
    }
    

    【讨论】:

      猜你喜欢
      • 2021-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多