2

私は、サーバーが同じインターフェースを公開している複数のサーバーと通信するプロジェクトに取り組んでいます(クラスタリングの場合のように)。ラウンドロビンを使用して、リクエストを送信するサーバーを選択します。これまで、Expressionを使用してClusterManagerを呼び出してきましたが、これにより、コードが醜くなります。また、単体テストが煩雑になり、メソッドパラメータの検証が少し難しくなります。また、ランダムな例外を除いてMoqでいくつかの問題が発生するようです(この投稿のトピックではありません)。

私は現在、アクションまたは関数の引数を使用したインターフェイスのMoqセットアップ後のドキュメントに記載されているように、サーバーと単体テストを呼び出しています

要点:

私は現在、次のアプローチを採用しています。

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)での呼び出しの翻訳については、2つのアイデアがあります。

アイデア 1IMethodCallMessageをlamda式(実行方法を理解できていません)に変換し、ClusterManagerに渡します。式の作成方法がわからないという問題を除いて、戻り値を再度処理します。一部のメソッドは値を返しますが、他のメソッドは返しません。そのため、これにはClusterManager.CallServerの複数のオーバーロードを維持することが含まれます。また、Invokeから戻るにはIMessageを作成する必要があります。

アイデア2 サーバーの呼び出しに現在使用しているWCF接続のTransparentProxyのRealProxyを取得し、メッセージを表示してInvokeを直接呼び出します。私の試行(統合テストを使用)では、サーバーを正常に呼び出すことができたようですが、ReturnMessageを調べると、戻り値がなく、ServiceChannelProxyがメッセージデータを取得しようとすると、ExceptionプロパティがArithmetricExceptionに設定されます。これは、テストで何か間違ったことをしたか、2つの別々のプロキシで同じLogicalCallContext(または他の何か)を使用できないことが原因である可能性があります。

これに対処する方法についての指針はありますか?アイデア2は最も単純に見え、コードの量が最も少なくなることを願っています。IServerExposedToClientのすべてのメソッドをクラスに実装して正しいサーバーで呼び出すことは、私がやりたいことではありません。

これに対処する方法についての指針はありますか?

4

1 に答える 1

2

ここにある情報を使用して、問題を解決することができました。以下のコードでは、プロキシは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 に答える