2010-01-30 211 views
18

我有這樣的WCF方法WCF依賴注入和抽象工廠

Profile GetProfileInfo(string profileType, string profileName) 

和業務規則:

如果profileType是 「A」,從數據庫中讀取。

如果profileType爲「B」,則從xml文件讀取。

問題是:如何使用依賴注入容器來實現它?

回答

22

讓我們先假設你有一個IProfileRepository是這樣的:

public interface IProfileRepository 
{ 
    Profile GetProfile(string profileName); 
} 

以及兩種實現方式:DatabaseProfileRepositoryXmlProfileRepository。問題是你想根據profileType的值選擇正確的。

您可以通過引入該抽象工廠做到這一點:

public interface IProfileRepositoryFactory 
{ 
    IProfileRepository Create(string profileType); 
} 

假設IProfileRepositoryFactory已經被注入到服務實現,你現在可以實現GetProfileInfo方法是這樣的:

public Profile GetProfileInfo(string profileType, string profileName) 
{ 
    return this.factory.Create(profileType).GetProfile(profileName); 
} 

IProfileRepositoryFactory的具體實現可能如下所示:

public class ProfileRepositoryFactory : IProfileRepositoryFactory 
{ 
    private readonly IProfileRepository aRepository; 
    private readonly IProfileRepository bRepository; 

    public ProfileRepositoryFactory(IProfileRepository aRepository, 
     IProfileRepository bRepository) 
    { 
     if(aRepository == null) 
     { 
      throw new ArgumentNullException("aRepository"); 
     } 
     if(bRepository == null) 
     { 
      throw new ArgumentNullException("bRepository"); 
     } 

     this.aRepository = aRepository; 
     this.bRepository = bRepository; 
    } 

    public IProfileRepository Create(string profileType) 
    { 
     if(profileType == "A") 
     { 
      return this.aRepository; 
     } 
     if(profileType == "B") 
     { 
      return this.bRepository; 
     } 

     // and so on... 
    } 
} 

現在,你只需要得到您所選擇的DI容器連線一切,爲你...

+0

那些順序的'ifs'可以被替換成更快/更清晰的'switch/case'。 'profileType'確實應該是一個枚舉,而不是任意的字符串。除此之外,這是一個很好的答案。 :) – Aaronaught

+3

是的,沒有意見分歧,但我只是與OP給出的API :) –

+0

如果我不知道在編譯時存儲庫的數量它可以改變? 如果我的wcf只與日誌庫和這些存儲庫有依賴關係,那麼最佳的DI容器選擇在哪裏? 是MEF在這種情況下的一個很好的選擇? – tartafe

4

馬克偉大的回答,但是給出的解決方案是不抽象工廠但標準實施工廠模式。請檢查Marks類如何符合標準工廠模式UML圖。 Click here to see above classes applied to Factory pattern UML

由於在工廠模式中,工廠知道具體的類,我們可以使ProfileRepositoryFactory的代碼更簡單,如下所示。將不同的存儲庫注入工廠的問題是每次添加新的具體類型時都會有更多的代碼更改。下面的代碼,你只需要更新的開關,包括新的具體類

 

    public class ProfileRepositoryFactory : IProfileRepositoryFactory 
    { 
     public IProfileRepository Create(string profileType) 
     { 
      switch(profileType) 
      { 
       case "A": 
        return new DatabaseProfileRepository(); 

       case "B": 
        return new XmlProfileRepository(); 
      } 
     } 
    } 
 

抽象工廠是用於創建相關或依賴的對象,而無需指定它們具體的類更高級的模式。可用的UML類圖here很好地解釋了它。