6

Autofac 3.0將有一個MultitenantIntegration支持和its preview release is out現在。爲了嘗試一下,我創建了以下配置一個ASP.NET Web API應用程序:Autofac多租戶IoC容器在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每個租戶。我在這個階段,兩個問題,我是不是能解決:

  1. 我開箱即用的只是這個演示應用程序提供RequestParameterTenantIdentificationStrategy這裏作爲TenantIdentificationStrategy。我可以通過實施ITenantIdentificationStrategy界面來創建自定義TenantIdentificationStrategy。然而,TryIdentifyTenant方法ITenantIdentificationStrategy使您依賴於一個靜態實例,如HttpContext.Current這是我不想在ASP.NET Web API環境中的東西,因爲我希望我的API託管不可知論者(我知道我可以委託這項工作的託管層,但我寧願不)。有沒有另一種方式來實現這一點,我不會依賴一個靜態實例?
  2. 我也有機會登記爲以下租戶特定實例:

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

    然而,我的情形之一,需要我通過構造函數的參數傳遞房客的名字,我很想有類似下面:

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

    目前沒有這樣的API。還有另外一種方法可以達到這個要求嗎?或者這種要求沒有任何意義?

回答

4

多租戶支持已經可用很長時間了,只是3.0版本是我們第一次使用NuGet軟件包。 :)

如記錄,RequestParameterTenantIdentificationStrategy只是一個非常簡單的例子,顯示了一種可能(和不推薦)的方式來確定租戶。您必須自己選擇如何根據運營環境來識別租戶。它可能來自於web.config的值,環境變量或當前環境中的其他東西。如果你不想使用HttpContext.Current,不要。這取決於你從哪裏獲得信息。

(在RPTIStrategy的說明 - 未使用查詢字符串或請求參數作爲租戶ID機制建議的一部分,我在我的生產應用程序使用HttpContext,它工作正常這裏只有這麼多,你可以抽象。在你不得不實際觸摸裸機之前)。

沒有辦法提供您要求的lambda註冊語法,主要是因爲tenant未通過解析過程。解決過程如下:

  1. 確定租戶的策略。
  2. 查找租戶的配置生命週期範圍。
  3. 使用標準的Autofac Resolve風格語法。

這是故意簡單和類似於現有的操作。在解決的時候,屬於租戶的子生命週期範圍是帶有租戶ID的標記爲,但解析操作不知道租戶ID ......所以lambda不起作用(並且可能贏得了因爲它會改變Autofac工作方式的基礎內部結構)。

來完成你在找什麼,在註冊時可以使用InstancePerTenant擴展的組合...

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

...和註冊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(); 

再次,你要仔細檢查我,但我很確定(或一個小的變化)應該工作,以獲得你想要的。

+0

謝謝特拉維斯。真的很有幫助。你最後的樣品真的是我正在尋找的。我應該考慮過之前:)所以,我的ITenantIdentificationStrategy需要真正的靜態對象。那麼對我來說沒有其他選擇,而不是將'TenantIdentificationStrategy'委託給具有每個請求靜態上下文的宿主層。 – tugberk