2017-01-24 36 views
-2

假設您擁有多租戶應用程序。一個Tenant有各種屬性:針對租戶特定業務邏輯的C#體系結構/模式

public class Tenant{ 
    public string TenantName {get; set;} 
    public string TenantUrl {get; set;} 
} 

這樣,當我服務層發送電子郵件,例如,我可以做到以下幾點:

SendEmail(Tenant.FromEmailAddress, recipientEmailAddress) 

這對於性質效果很好。在我的業務邏輯許多地方,我遇到了必須考慮租戶特定行爲的情況。一個例子是網頁檢索照片:

public List<string> GetPhotoUrls(){ 
    if(currentTenant == TenantA){ 
     // logic to go off to retrieve from one third party 
    } else if (currentTenant == TenantB){ 
     // totally different logic 
    } else... // one for each tenant 

    // do some stuff 
    // return stuff 
} 

GetPhotoUrls是一個簡單的例子 - 但也有這樣的情況下,在我的業務邏輯的許多地方。我正在尋找一個簡單的模式,我可以定義和實施特定於租戶的邏輯。總體目標是在一個地方獲得所有特定於租戶的邏輯,因此租戶的創建和定義非常簡單。

我想開發者體驗到的線沿線閱讀:

public List<string> GetPhotoUrls(){ 
    currentTenant.GetPhotoUrls(); // define this logic on the tenant object somehow 
    // do some stuff 
    // return stuff 
} 

什麼模式/構造可用來實現這一目標?

+0

什麼似乎很奇怪的看看是你的租戶那裏獲取數據租戶是硬編碼的... –

+1

我不認爲你的photourl邏輯是租戶特定的,而不是照片來源特定的,所以每個租戶應該有一個你分配的photoprovider,這取決於它是什麼類型的租戶? –

+0

@JanneMatikainen - 這是一個不好的例子 - 邏輯確實不同。 – SB2055

回答

0

在你的情況下使用策略模式。當您看到switch語句或多個if語句來簡化客戶端以便將自定義實現委託給從屬接口時,最好應用該模式。您也可以結合使用工廠模式。爲了說明這一點:

public interface ITenant{ 
    List<string> GetPhotoUrls(); 
} 

public class TenantA:ITenant{ 
    public string TenantName {get; set;} 
    public string TenantUrl {get; set;} 
    public List<string> GetPhotoUrls(){ 
     //A implementation 
    } 
} 

public class TenantB:ITenant{ 
    public string TenantName {get; set;} 
    public string TenantUrl {get; set;} 
    public List<string> GetPhotoUrls(){ 
     //B implementation 
    } 
} 

public class SomeTenantApp{ 
    public SomeTenantApp(ITenant tenant){ 
     _tenant = tenant; 
    } 

    public void DoSomething(){ 
    var urls = _tenant.GetPhotoUrls(); 
    //do something 
    } 
} 

public static class TenantFactory{ 
    public static ITenant Create(string id) 
    { 
     //logic to get concrete tenant 
     return concreteTenant; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var tenant = TenantFactory.Create("A"); 
     var app = var SomeTenantApp(tenant); 
     app.DoSomething(); 
    } 
} 

客戶端(SomeTenantApp)將不必更改。您將實現委託給擁有邏輯的具體類。

0

如果您想構建SaaS,我強烈建議使用ASP.NET Core和依賴注入來克服多租戶問題。

你可以定義你的房客類:

public class AppTenant 
{ 
    public string Name { get; set; } 
    public string[] Hostnames { get; set; } 
} 

接下來,您可以從當前請求

public class AppTenantResolver : ITenantResolver<AppTenant> 
{ 
    IEnumerable<AppTenant> tenants = new List<AppTenant>(new[] 
    { 
     new AppTenant { 
      Name = "Tenant 1", 
      Hostnames = new[] { "localhost:6000", "localhost:6001" } 
     }, 
     new AppTenant { 
      Name = "Tenant 2", 
      Hostnames = new[] { "localhost:6002" } 
     } 
    }); 

    public async Task<TenantContext<AppTenant>> ResolveAsync(HttpContext context) 
    { 
     TenantContext<AppTenant> tenantContext = null; 
     // it's just a sample... 
     var tenant = tenants.FirstOrDefault(t => 
      t.Hostnames.Any(h => h.Equals(context.Request.Host.Value.ToLower()))); 

     if (tenant != null) 
     { 
      tenantContext = new TenantContext<AppTenant>(tenant); 
     } 

     return tenantContext; 
    } 
} 

解決租戶包裝它:

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddMultitenancy<AppTenant, AppTenantResolver>(); 
} 

獲取當前租戶(只要你需要它):

public class HomeController : Controller 
{ 
    private AppTenant tenant; 

    public HomeController(AppTenant tenant) 
    { 
     this.tenant = tenant; 
    } 
    . 
    . 
    . 
} 

欲瞭解更多信息,在SaasKit
Building multi-tenant applications with ASP.NET Core (ASP.NET 5)