2010-12-08 64 views
0

現在我已經使用適配器模式從調用代碼中抽象我的WCF服務客戶端,這樣我就可以有效地單元測試業務對象而不依賴於服務客戶端。例如:適配器模式與封裝衝突嗎?

public class MyBusinessObject 
{ 
    private ITheService _service; 

    public MyBusinessObject(ITheService service) { _service = service; } 

    public void DoSomethingOnTheServer() { _service.DoSomething(); } 
} 

現在適配器的接口和具體實現公開了與服務代理本身相同的合同。因此,繼續例如:

public interface ITheService 
{ 
    void DoSomething(); 
    ServerObject GetData(); 
} 

public class DefaultService : ITheService 
{ 
    public void DoSomething() { ... } 
    public ServerObject GetData() 
    { 
     using (var proxy = new ActualServiceClient()) 
     { 
      return proxy.GetData(); 
     } 
    } 
} 

這工作得很好,很好,我能夠有效地測試我的業務對象等

我的問題的事實,我從第二返回類型莖方法與服務強烈耦合。如果適配器返回了我要使用的類型的實例而不是來自服務的DTO /代理,那麼它是否更有意義並且與Adapter模式更一致?

如果是這樣,那麼我很擔心封裝。在典型的用例中,調用服務來檢索數據,然後將其填充到我的業務對象中。如果我想讓只讀屬性暴露給我的UI,那麼我不能將這些屬性的賦值委託給另一個對象,比如適配器。

想法?

回答

1

給它更多思考和一些額外的閱讀,我上面描述的方法更符合Bridge模式。這種認識幫助我看到了缺失的部分 - 適配器!就像Massimiliano說的那樣,我現在有一個位於我的業務對象和服務之間的適配器。適配器負責將WCF服務公開的POCO/DTO/Entity/...公開到我的業務對象中。

而不是我的業務對象在其構造函數中引用服務(ITheService),它現在需要對服務適配器(ITheServiceAdapter)的引用。此接口的樣子:

internal interface ITheServiceAdapter 
{ 
    void DoSomething(); 
    MyBusinessObject GetData(); 
} 

在具體實施(TheServiceAdapter),我使用AutoMapper來「適應」基於服務器的POCO/DTO返回由實際的服務到我的業務對象,如:

internal class TheServiceAdapter : ITheServiceAdapter 
{ 
    private ITheService _service; 

    public TheServiceAdapter(ITheService service) { _service = service; } 

    public void DoSomething() { ... } 

    public MyBusinessObject GetData() 
    { 
     var data = _service.GetData(); 

     return Mapper.Map<ServiceObject, MyBusinessObject>(data); 
    } 
} 

這工作很好,滿足我從我的業務對象抽象服務實現的要求。唯一與WCF代理類型綁定的代碼是適配器。另外,我仍然可以通過注入服務適配器的模擬實現來乾淨地單元測試我的業務對象。而且,因爲我選擇信任AutoMapper,所以我不需要單元測試適配器類,並通過集成測試來捕獲代碼中的任何問題。所以,一切都很好 - 對吧?

當然這還沒有解決封裝問題。幸運的是,Rockford Lhotka(CSLA的名氣)在他的書中有關這個主題的很好的論文。我的解決方案是通過將所有這些代碼放在一個單獨的程序集中,併爲setter提供內部作用域,使所有屬性只讀取消耗代碼,從而「僞裝」封裝。這允許適配器設置屬性,同時防止客戶端代碼執行相同的操作。

這並不完美,但它是一個解決方案。如果你有其他的想法似乎不是詭計,我很樂意聽到它們!

0

服務應該永遠不會返回只在「服務器端世界(WCF)上纔有意義的對象」,它不僅僅是一個耦合事項 我可以建議您應該創建一個POCO對象,該對象將由WCF。 您可以根據需要創建此對象:在這種情況下,您只能添加將會公開給用戶界面的只讀屬性。當然,您需要一個將您的複雜/服務器對象轉換爲POCO對象的對象。要實現此目的,您可以創建一個適配器用來構建POCO對象的類