使用RealProxy包装多个WCF连接
我正在从事一个项目,在这个项目中,我们的服务器与几个暴露相同接口的服务器通信(如集群中)。我们使用循环选择将请求发送到哪个服务器。到目前为止,我们一直在使用Expression调用ClusterManager,但这会导致一些糟糕的代码。这也使得单元测试变得混乱,验证方法参数也有点困难。这似乎也会导致Moq的一些问题和随机的例外(不是本文的主题) 我目前调用了本文中记录的服务器和单元测试 关于要点: 我目前的做法如下:使用RealProxy包装多个WCF连接,wcf,expression,realproxy,Wcf,Expression,Realproxy,我正在从事一个项目,在这个项目中,我们的服务器与几个暴露相同接口的服务器通信(如集群中)。我们使用循环选择将请求发送到哪个服务器。到目前为止,我们一直在使用Expression调用ClusterManager,但这会导致一些糟糕的代码。这也使得单元测试变得混乱,验证方法参数也有点困难。这似乎也会导致Moq的一些问题和随机的例外(不是本文的主题) 我目前调用了本文中记录的服务器和单元测试 关于要点: 我目前的做法如下: public interface IServerAdapter {
public interface IServerAdapter
{
void CallServer(Expression<Action<IServerExposingToClient>> methodToCall, out bool serverCalled);
}
private void DoSomething()
{
MainViewModel.ServerAdapter.CallServer(server => server.SaveServerSettings(ServerSettings));
}
ServerProxy是一个RealProxy,我需要将此调用转换为ClusterManager以执行对服务器的实际调用。目前,ClusterManager具有与CallServer相同的签名,这对于现有实现来说有点多余。对于调用调用(IMessage)的翻译,我有两个想法
想法1
将IMethodCallMessage转换为lamda表达式(我还不知道该怎么做),并将其传递给ClusterManager。除了我不知道如何创建表达式,然后再次处理返回值的问题。某些方法返回值,而其他方法不返回值,因此这需要保留ClusterManager.CallServer的多个重载。我还需要创建IMessage以从Invoke返回
创意2
获取我当前用于调用服务器的WCF连接的TransparentProxy的RealProxy,并使用我得到的消息直接调用Invoke。在我的试用(使用集成测试)中,我似乎能够成功调用服务器,但通过ReturnMessage查看,没有返回值,并且当ServiceChannelProxy尝试获取消息数据时,Exception属性设置为ArithMetriceException。这可能是因为我在测试中出错,或者我不能在两个单独的代理上使用相同的LogicalCallContext(或其他内容)
关于如何处理这个问题有什么建议吗?我更喜欢想法2,因为它似乎是最简单的,并且希望产生的代码量最少。在一个类中实现IServerExposingToClient中的所有方法以调用正确的服务器不是我想做的事情
关于如何处理这个问题有什么建议吗 使用找到的信息,我已经能够解决这个问题。在下面的代码中,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);
}
}
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);
}
}