2017-11-13 6 views
1

パラメータの型に基づいて、いくつかのハンドラロジックを実装したいと思います。 WebAPIのために例外フィルタ属性を実装する、例えば取る:C#:ジェネリック型の異なる複数のハンドラ

public class ExceptionFilterAttribute : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext context) 
    { 
     if (context.Exception is NotImplementedException) 
     { 
      context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented); 
     } 
    } 
} 

これは自分自身で完全に正常に見えますが、私がやりたいものを、例えば、例外の種類ごとに複数のハンドラを追加されますDbEntityValidationException、またはビジネスロジックがスローする可能性のあるその他のカスタム例外があります。

もちろん、例外が特定のタイプであるかどうかを確認するために別のブロックを簡単に追加することはできますが、これを避けてさまざまな例外タイプの処理を別々のクラスに分割します。

そのようなクラスのためのインターフェイスがこの

public interface ExceptionHandler<T> where T : Exception { 
    void Handle(HttpActionExecutedContext context, T exception); 
} 

のようになります。私は今、ExceptionFilterAttribteにコレクションにこれらExceptionHandler秒の実装を追加したいと思いますので、ハンドラがある場合、私は確認することができます例外が発生した場合、適切なキャストを行い、ハンドラを呼び出します。しかし、私は単一のコレクション(例えばclass DbEntityValidationExceptionHandler : ExceptionHandler<DbEntityValidationException>)に異なるジェネリック型でTExceptionHandlerインタフェースの実装を追加することはできませんので、私は、この部分を実装しなければならないか、把握することはできません。

private List<ExceptionHandler<Exception>> handlers = new List<ExceptionHandler<Exception>>() 
    { 
     new DbEntityValidationExceptionHandler() // does not compile... 
    }; 

どのようにすることができますコレクション内の私のExceptionHandler<T>インターフェイスのさまざまな実装への参照を保持しますか?あるいは、このアプローチは完全に間違っていますか?そして、このような状況を処理するもっと良い方法がありますか?どんな提案も大歓迎です。あなたがバリアントジェネリックインターフェイスでこれを行うことができます

+0

、彼らが実装することを、一般的な制約タイプ( 'Exception'を)かかり' Handle'方式と非ジェネリックインターフェイスを作成し、コレクションを作りますそのタイプ。 –

+1

できません。ジェネリックは完全ではありません。フレームワークで一般的なほとんどのものは、インターフェイスの非ジェネリックフォームを実装しています(IEnumerable 、すべてのコレクションでIEnumerableなど)。それは、何かがというものとは異なるタイプのものであるという事実に沸きます。。共通の基本タイプまたはインタフェースを共有しない限り、同じ方法で複数の型を処理することはできません。あなたのご意見をお寄せいただきありがとうございます。 – Will

+0

好奇心の念から、処理する例外の種類ごとに 'if'ブロックを追加するだけではなく、そのような振る舞いの実装についてどう思いますか? – forrert

答えて

2

class TestException : Exception 
{ 
} 
class TestException2:Exception 
{ 
} 

class foo : ExceptionHandler<TestException> { } 
class bar : ExceptionHandler<TestException2> { } 

public interface ExceptionHandler<out T> where T : Exception 
{ } 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<ExceptionHandler<Exception>> a = new List<ExceptionHandler<Exception>>(); 
     a.Add(new foo()); 
     a.Add(new bar()); 
    } 

} 
+1

その1つを読んでいた - しかし、確かに 'アウト'正しいです、あなたはT入力パラメータ(例えば、 "void HandleException(T例外)")?そして、実際にどのように動作するのか興味があります。List >とExceptionオブジェクトがあれば、マッチングハンドラをどのように取得し、安全クラスの例外を安全クラスに渡すのですか? –

+1

@DylanNicholsonはい、ここで使うのが正しいです。ジェネリックインターフェイスをキャストダウンする唯一の方法はです。 OPが行うことができるのは、現在のハンドラが指定された例外を処理できるかどうかを調べるためにT型を返すフィールドを追加することです。HandleException関数はこれを指摘してくれたので、(例外e) – Steve

+0

@Steveを受け取ります。私は 'out 'キーワードがまだ分からなかった。私は@DylanNicholsonが指摘しているように私のケースではこれはうまくいかないと思うが、メソッドの引数としてジェネリック型を使う必要があるだろう。 – forrert

関連する問題