2

我正在开发一个项目,我们的服务器与多个暴露相同接口的服务器进行通信(如集群)。我们使用循环来选择将请求发送到哪个服务器。到目前为止,我们一直在使用 Expression 来调用我们的 ClusterManager,但这会导致一些丑陋的代码。它还使单元测试变得混乱,并且有点难以验证方法参数。它似乎也导致 Moq 出现一些随机异常问题(不是本文的主题)。

我目前调用服务器和单元测试,如Moq Setup 后所述,用于带有操作或函数参数的接口

言归正传:

我目前有以下方法:

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中的所有方法以调用正确的服务器并不是我想做的事情。

有关如何处理此问题的任何指示?

4

1 回答 1

2

使用在这里找到的信息,我已经能够解决这个问题。在下面的代码中,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);
    }
}
于 2012-12-14T22:07:59.253 回答