2012-12-06 37 views
2

我正在開發一個項目,我們的服務器與暴露相同界面的多個服務器(如在羣集中)進行通信。我們使用循環法來選擇將我們的請求發送給哪個服務器。到目前爲止,我們一直在使用Expression來調用我們的ClusterManager,但是這會產生一些難看的代碼。它也使得單元測試變得麻煩,並且有點難以驗證方法參數。這似乎也導致與Moq隨機例外的一些問題(不是這篇文章的主題)。使用RealProxy包裝多個WCF連接

我當前調用服務器和單元測試作爲記錄在後Moq Setup for interface with action or function arguments

在給點意見:

目前,我有以下方法:

public interface IServerAdapter 
{ 
    void CallServer(Expression<Action<IServerExposingToClient>> methodToCall, out bool serverCalled); 
} 

private void DoSomething() 
{ 
    MainViewModel.ServerAdapter.CallServer(server => server.SaveServerSettings(ServerSettings)); 
} 

我想改變這如下所示:

public interface IServerAdapter 
{ 
    IServerExposingToClient ServerProxy { get; } 
} 

private void DoSomething() 
{ 
    MainViewModel.ServerAdapter.ServerProxy.SaveServerSettings(ServerSettings); 
} 

ServerPr oxy是一個RealProxy,我需要將此調用轉換爲ClusterManager以執行對服務器的實際調用。目前,ClusterManager對於CallServer具有相同的簽名,這對於現有的實現來說有點冗餘。對於Invoke(IMessage)中的調用翻譯,我有兩個想法。

理念1 翻譯IMethodCallMessage的LAMDA表達式(我一直無法弄清楚如何做),並把它傳給ClusterManager。除了我不知道如何創建表達式的問題,然後再處理返回值。一些方法返回一個值,而另一些則沒有,所以這涉及到保留多重的ClusterManager.CallServer。我還需要創建IMessage以從Invoke返回。

理念2 找我目前使用調用服務器WCF連接的TransparentProxy的RealProxy,並直接調用調用與我的消息。在我的試驗中(使用集成測試),我似乎能夠成功調用服務器,但是通過ReturnMessage查看,沒有返回值,並且ServiceChannelProxy嘗試獲取消息數據時,Exception屬性設置爲ArithmetricException。這可能是因爲我在測試中做了錯誤,或者我不能在兩個獨立的代理上使用相同的LogicalCallContext(或其他)。

任何關於如何處理這個問題的指針?我更喜歡想法2,因爲它似乎是最簡單的,並希望導致最少的代碼。在類中調用IServerExposingToClient中的所有方法以調用正確的服務器並不是我想要做的事情。

任何關於如何處理這個問題的指針?

回答

2

使用找到的信息here,我已經能夠解決這個問題。在下面的代碼中,proxy是WCF服務通道的ICommunicationObject。似乎工作得很好。

public override IMessage Invoke(IMessage msg) 
{ 
    var methodCall = (IMethodCallMessage)msg; 
    var proxy = FindNextProxy(); 
    try 
    { 
     MethodBase methodBase = methodCall.MethodBase; 
     object[] args = methodCall.Args; 
     object returnValue = methodBase.Invoke(proxy, args); 
     return CreateReturnMessage(returnValue, methodCall); 
    } 
    catch (TargetInvocationException ex) 
    { 
     return CreateReturnMessage(ex.InnerException, methodCall); 
    } 
}