web-dev-qa-db-ja.com

Reflection MethodInfo.Invoke()はメソッド内からの例外をキャッチします

リフレクションを介して関数を実行するMethodInfo.Invoke()への呼び出しがあります。呼び出しは_try/catch_ブロックでラップされていますが、呼び出している関数によってスローされた例外をキャッチしません。

次のメッセージが表示されます。

例外はユーザーによって処理されませんでした。


なぜMethodInfo.Invoke()は、例外がInvoke()の外でキャッチされるのを防ぐのですか?
どうすればバイパスできますか?

27
Rodniko

編集:私があなたの問題を理解しているように、問題は純粋にIDE 1です; VSがMethodInfoの呼び出しによってスローされた例外をキャッチされなかったものとして扱うのが好きではない場合、この問題を解決する方法については、こちらで読むことができます。 IDEでTargetInvocationExceptionがキャッチされていないものとして扱われるのはなぜですか? これはバグのようです/設計上、どういうわけか、適切な回避策がその回答に記載されています。

私が見るように、あなたにはいくつかの選択肢があります:

  1. MethodInfo.Invokeを使用してTargetInvocationExceptionをキャッチし、そのInnerExceptionプロパティを調べることができます。その答えで述べられているように、IDE問題を回避する必要があります。

  2. Delegateから適切なMethodInfoを作成し、代わりにそれを呼び出すことができます。この手法では、スローされた例外はラップされません。さらに、このアプローチdoesはデバッガでうまく機能しているようです。 「キャッチされていない例外」ポップアップが表示されません。

両方のアプローチを強調する例を次に示します。

class Program
{
    static void Main()
    {
        DelegateApproach();
        MethodInfoApproach();
    }

    static void DelegateApproach()
    {
        try
        {
            Action action = (Action)Delegate.CreateDelegate
                                   (typeof(Action), GetMethodInfo());
            action();
        }
        catch (NotImplementedException nie)
        {

        }
     }

    static void MethodInfoApproach()
    {
        try
        {
            GetMethodInfo().Invoke(null, new object[0]);
        }
        catch (TargetInvocationException tie)
        {
            if (tie.InnerException is NotImplementedException)
            {


            }
        }
    }

    static MethodInfo GetMethodInfo()
    {
        return typeof(Program)
                .GetMethod("TestMethod", BindingFlags.NonPublic | BindingFlags.Static);
    }    

    static void TestMethod()
    {
        throw new NotImplementedException();
    }
}
28
Ani

どのようにして例外をキャッチしようとしていますか?通常、Invoke()の呼び出しからスローされるのは、System.Reflection.TargetInvocationExceptionのラップ例外インスタンスです。あなたが追いかけている実際の例外はInnerExceptionにあります。

try
{
    method.Invoke(target, params);
}
catch (TargetInvocationException ex)
{
    ex = ex.InnerException; // ex now stores the original exception
}
19
Quick Joe Smith