2012-12-06 35 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); 
    } 
}