租户IoC容器在ASP.NET Web API应用程序中

Autofac 3.0将具有MultitenantIntegration支持,其预览版本现已发布。 为了试用它,我使用以下配置创建了一个ASP.NET Web API应用程序:

public class Global : System.Web.HttpApplication {

    protected void Application_Start(object sender, EventArgs e) {

        var config = GlobalConfiguration.Configuration;
        config.Routes.MapHttpRoute("Default", "api/{controller}");
        RegisterDependencies(config);
    }

    public void RegisterDependencies(HttpConfiguration config) {

        var builder = new ContainerBuilder();
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

        // creates a logger instance per tenant
        builder.RegisterType<LoggerService>().As<ILoggerService>().InstancePerTenant();

        var mtc = new MultitenantContainer(
            new RequestParameterTenantIdentificationStrategy("tenant"),
            builder.Build());

        config.DependencyResolver = new AutofacWebApiDependencyResolver(mtc);
    }
}

它完成工作并创建一个LoggerService实例作为每个租户的ILoggerService 。 在这个阶段我有两个问题,我无法解决:

  • 我在此提供的RequestParameterTenantIdentificationStrategy框中用作TenantIdentificationStrategy,仅用于此演示应用程序。 我可以通过实施ITenantIdentificationStrategy界面来创建自定义TenantIdentificationStrategy。 然而, TryIdentifyTenant的方法ITenantIdentificationStrategy让你依靠静态实例如HttpContext.Current这是一件好事,因为我希望我的API被托管无关,我不在ASP.NET Web API环境想(我知道我可以将这项工作委托给托管层,但我宁愿不要)。 有没有另一种方式来实现这一点,我不会依赖一个静态实例?
  • 我也有机会注册租户特定实例如下:

    mtc.ConfigureTenant("tenant1", cb => cb.RegisterType<Foo>()
                                        .As<IFoo>().InstancePerApiRequest());
    

    但是,我的一个情况要求我通过构造函数参数传递承租人名称,并且我希望具有以下内容:

    mtc.ConfigureTenant((cb, tenantName) => cb.RegisterType<Foo>()
                                        .As<IFoo>()
                                        .WithParameter("tenantName", tenantName)
                                        .InstancePerApiRequest());
    

    目前没有这样的API。 还有另外一种方法可以达到这个要求吗?或者这种要求没有任何意义?


  • 多租户支持已经有很长时间了,只是3.0版本是我们第一次为它开发NuGet软件包。 :)

    正如文件所述, RequestParameterTenantIdentificationStrategy只是一个非常简单的例子,显示了一种可能的(而不是推荐的 )方法来识别租户。 您必须自己选择如何根据运营环境来识别租户。 它可能来自web.config值,环境变量或当前环境中的其他东西。 如果你不想使用HttpContext.Current ,不要。 这取决于你从哪里获得信息。

    (有关RPTIStrategy - 不推荐的部分是使用查询字符串或请求参数作为租户ID机制。我在生产应用程序中使用HttpContext并且它工作正常。只有很多可以在您拥有之前抽象出来实际触摸裸机。)

    提供您要求的lambda注册语法是没有办法的,主要是因为租户没有通过解析过程。 解决过程是:

  • 用策略识别租户。
  • 查找租户的配置生命周期范围。
  • 使用标准的Autofac Resolve风格语法。
  • 这是故意简单和类似于现有的操作。 在解决的时候,属于租户的子生命周期范围被标记为租户ID,但解析操作不知道租户ID ......所以lambda不起作用(并且可能不会很快就会发生,因为它会改变Autofac工作方式的基础内部结构)。

    要完成您要查找的内容,您可以在注册时使用InstancePerTenant扩展名的组合...

    var builder = new ContainerBuilder();
    builder.RegisterType<Foo>().As<IFoo>().InstancePerTenant();
    

    ...并将ITenantIdentificationStrategy注册为ITenantIdentificationStrategy中的依赖项。

    builder.Register(myIdStrategy).As<ITenantIdentificationStrategy>();
    

    然后让您的班级直接采用ITenantIdentificationStrategy而不是租户ID。 改用策略来取得租户ID。

    如果你真的想变得有趣,你可以注册一个解析ID策略的键控lambda,然后获得租户ID。 然后,您可以像添加参数注册一样对象,但使用键控服务。 (我现在要回忆起来,所以你必须仔细检查我的语法,但它会是这样的......)

    builder.Register(c => 
           {  var s = c.Resolve<ITenantIdentificationStrategy>();
              object id;
              s.TryIdentifyTenant(out id);
              return id;
           }).Keyed<object>("tenantId");
    
    builder.RegisterType<Foo>()
           .As<IFoo>()
           .WithParameter(
             (pi, c) => pi.Name == "tenantId",
             (pi, c) => c.ResolveKeyed<object>("tenantId"))
           .InstancePerApiRequest();
    

    再一次,你会想再次检查我,但我很确定(或一个小的变化)应该工作,以获得你想要的。

    链接地址: http://www.djcxy.com/p/67749.html

    上一篇: tenant IoC Container in an ASP.NET Web API Application

    下一篇: Calling python script from TCL and creating a file atomically