2

リフレクションを使用してアセンブリ B と C (これも .NET) を読み込む .NET アセンブリ A があるとします。これら 2 つのアセンブリは両方とも、多数の大きなインターフェイスを実装しています (両方とも同じです)。メソッドが A で呼び出されると、B に作業を行わせようとします。ただし、B は信頼性が低く、例外をスローする可能性があります。現在、A には 2 つのモードがあります。1 つは例外を A の呼び出し元に伝播するモードで、もう 1 つはより安定した (しかしパフォーマンスが低い) C で一致するメソッドを呼び出すモードです。

以下に示すように、すべての呼び出しをコードで囲むだけで、すべての B のインターフェイスの巨大な実装で B が公開するすべてのメソッドをラップするよりも、このシナリオを実装するためのより良い方法 (少ないコード) はありますか? アセンブリ B と C は、選択されたエラー処理アプローチについて何も知らないため、ロジックを実装できません。

public class BErrorWrapper : I1, I2, I3{
   ...
   public int DoSomeWork(int num){
      if (FailWithExceptions)
      {
         try
         {
            return B.DoSomeWork(num);
         }
         catch(MyLibException e)
         {
            return C.DoSomeWOrk(num);
         }
      }
      else
      {
         return B.DoSomeWork(num);
      }
   }
   ...
}
4

3 に答える 3

2

これを行うと、繰り返しを節約できます。

public class BErrorWrapper : I1, I2, I3{
   ...
   public int DoSomeWork(int num){
      try
      {
         return B.DoSomeWork(num);
      }
      catch(MyLibException e)
      {
         if (FailWithExceptions) throw;
         return C.DoSomeWOrk(num);
      }
   }
   ...
}
于 2008-11-19T09:31:13.490 に答える
1

うーん...いくつかのコードを保存するために、以下のようにデリゲートを介してほとんどの一般的な署名をラップできます(明確にするためにコアビットのみを含めていることに注意してください-ただし、簡単に追加できますFailWithExceptions):

    static void TryWithFallback<T>(Action<T> primary, Action<T> fallback, T arg)
    {
        try
        {
            primary(arg);
        }
        catch // add your other regular code here...
        {
            fallback(arg);
        }
    }

次に、これを次の方法で実装に再利用できます。

    TryWithFallback(b.DoSomeWork, c.DoSomeWork, num);

明らかに、次のような関連コードの署名をいくつか追加できます。

    static TResult TryWithFallback<T, TResult>(Func<T, TResult> primary, Func<T, TResult> fallback, T arg)
    {
        try
        {
            return primary(arg);
        }
        catch
        {
            return fallback(arg);
        }
    }
于 2008-11-19T09:37:20.420 に答える
1

リフレクションと System.CodeDom を使用してコードを生成することを検討することをお勧めします。最近、クライアント側では使用したくないが、クライアント側では使用できるパラメータ型を含むシグネチャを持つ多くのメソッドを持つ非常に大きなインターフェイスを持つ COM 相互運用アセンブリのラッパーを作成しようとしたときに、同様の問題が発生しました。クライアント側で必要な型に簡単に変換できます。これらは、クライアント コードをより冗長にする 'ref' パラメータでもありました。メソッドには、クライアント側で公開したい意味のある名前を持つさまざまな数のパラメーターがありました。

A と B のインスタンスのメンバーを持つラッパーの基本クラスを記述します。派生ラッパー クラスを生成するコード生成クラスを記述します。次に、コード生成は、ラッパーが実装する必要がある各インターフェイスのメソッドを反復処理し、必要なエラー処理構造内で A と B を呼び出すための適切なコードを含むメソッドとメソッド本体を追加する必要があります。A と B を呼び出すために生成するコードは、呼び出すメソッドのシグネチャに依存しますが、生成または呼び出されるメソッドのパラメーターを繰り返し処理することで実現するのは難しくありません。

コードを投稿することもできますが、少し違うことをしているので、MSDN または他の公開サンプルに戻ったほうがよいと思います。私が言えることは、これが驚くほど簡単で堅牢であることがわかったということだけです。

生成されたコードではなくコード生成コードをチェックインし、ビルドの一部としてコード生成を実行することをお勧めします。

于 2008-11-19T10:45:48.520 に答える