我正在开发一个项目,我们的服务器与几个暴露相同接口的服务器通信(如在群集中)。我们使用循环法来选择将请求发送到的服务器。到目前为止,我们一直使用Expression来调用我们的ClusterManager,但这导致了一些丑陋的代码。它还使单元测试变得混乱,并且有点难以验证方法参数。它似乎也会导致Moq出现一些随机异常的问题(不是本文的主题)。
我目前正在调用帖子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);
}
ServerProxy是一个RealProxy,我需要将此调用转换为ClusterManager以执行对服务器的实际调用。目前,ClusterManager具有与CallServer相同的签名,这对于现有实现来说有点多余。为了在Invoke(IMessage)中转换调用,我有两个想法。
创意1 将IMethodCallMessage转换为lamda表达式(我无法弄清楚如何操作)并将其传递给ClusterManager。除了我不知道如何创建表达式的问题,然后再次处理返回值。某些方法返回值,而其他方法则不返回,因此这涉及保留ClusterManager.CallServer的多个重载。我还需要创建IMessage以从Invoke返回。
创意2 获取我当前用来调用服务器的WCF连接的TransparentProxy的RealProxy,并直接使用我的消息调用Invoke。在我的试验中(使用集成测试),我似乎能够成功调用服务器,但查看ReturnMessage,没有返回值,并且当ServiceChannelProxy尝试获取消息数据时,Exception属性设置为ArithmetricException。这可能是因为我在测试中做错了,或者我不能在两个单独的代理上使用相同的LogicalCallContext(或其他东西)。
有关如何处理此事的任何指示?我更喜欢 Idea 2 ,因为它似乎是最简单的,并且希望能够产生最少量的代码。在类中 IServerExposingToClient 中实现所有方法以在正确的服务器上调用不是我想要做的事情。
有关如何处理此事的任何指示?
答案 0 :(得分: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);
}
}