2012-08-09 48 views
0

我有一組註冊到StructureMap的組件。根據實際承租人,解決組件問題的最佳方法是什麼?如何用StructureMap解決行爲變化?

小示例: 有兩個租戶,比如Yellow和Green。我有一個IValidator有兩個實現:YellowValidatorGreenValidator。 假定應用程序是MVC,並且該帳號來自URL。 因此,我只需要根據租戶注入適當的IValidator

我見過很多針對多租戶應用程序的解決方案,這些解決方案只處理多租戶數據,根據租戶正常配置不同的數據庫。這隻涉及參數傳遞。但是,行爲發生變化的情況就是這種情況,而不是數據。我希望IoC容器透明地解析正確的實例。

編輯:更多信息: 該IValidator接口有一個簡單的方法bool Validate(),但實施需要一些注射。

還有其他的自定義驗證器,但它們被兩個租戶使用。

根據URL有明確的帳篷策略。這意味着每個請求可以有不同的租戶,並且單個應用程序可以爲兩個租戶提供服務。

+1

你能否給出更多的背景信息,比如:「IValidator」接口實際上是怎樣的?驗證者目前如何註冊。 「YellowValidator」和「GreenValidator」是系統中唯一的兩個驗證程序嗎?還是有很多驗證程序幾乎都用於兩個租戶?只有幾個不同?你如何確定租戶是什麼?每個Web應用程序/應用程序域是否有一個租戶(在啓動時確定,可能以XML格式註冊),​​還是同時有多個租戶,每個請求可以有不同的租戶。 – Steven 2012-08-09 11:21:58

回答

1

皮膚貓有很多種方法。我很難猜測你的應用程序的設計,所以這是一個想法。需要考慮的事情是將驗證器隱藏在composite之後,以允許接口的用戶不知道有多少實現。這種複合材料可以是這樣的:

public class ValidatorComposite : IValidator 
{ 
    private IEnumerable<IValidator> validators; 

    public ValidatorComposite(
     IEnumerable<IValidator> validators) 
    { 
     this.validators = validators; 
    } 

    public bool Validate(object instance) 
    { 
     return this.validators.All(v => v.Validate(instance)); 
    } 
} 

您可以創建多個複合材料,其中的關鍵是租戶的名稱按鍵註冊(但沒有密鑰註冊可能是一樣簡單)。那些複合材料可以用另一個複合材料進行包裝,這些複合材料將委託給適當的承租人專用複合材料。這樣的租戶選擇複合看起來是這樣的:

public class TenantValidatorComposite : IValidator 
{ 
    private ITenantContext tenantContext; 
    private IValidator defaultValidator; 
    private IDictionary<string, IValidator> tenantValidators; 

    public ValidatorComposite(
     ITenantContext tenantContext, 
     IValidator defaultValidator, 
     IDictionary<string, IValidator> tenantValidators) 
    { 
     this.tenantContext = tenantContext; 
     this.defaultValidator = defaultValidator; 
     this.tenantValidators = tenantValidators; 
    } 

    public bool Validate(object instance) 
    { 
     string name = this.tenantContext.CurrentTenant.Name; 

     return this.defaultValidator.Validate(instance) && 
      this.tenantValidators[name].Validate(instance); 
    } 
} 

ITenantContext是一種抽象,使您可以在當前上下文中獲得當前的租戶。你可能已經到位類似的東西,但我想一個實現這個樣子:

class UrlBasedTenantContext : ITenantContext 
{ 
    public Tenant Current 
    { 
     get 
     { 
      // Naive implementation. 
      if (HttpContext.Current.Request.Url.Contains("tenant1")) 
      { 
       return Tenant1; 
      } 

      return Tenant2; 
     } 
    } 
} 

創建TenantValidatorComposite很容易:

var defaultValidator = CompositeValidator(
    GetAllDefaultValidators()); 

var tenantValidators = new Dictionary<string, IValidator>() 
{ 
    { "tenant1", new CompositeValidator(GetValidatorsFor("tenant1")) }, 
    { "tenant2", new CompositeValidator(GetValidatorsFor("tenant2")) }, 
}; 

var tenantValidator = new TenantValidatorComposite(
    new UrlBasedTenantContext(), 
    defaultValidator, 
    tenantValidators); 

我希望這有助於。