Reflection MethodInfo.Invoke () ловит исключения изнутри метода - PullRequest
23 голосов
/ 07 ноября 2010

У меня есть вызов MethodInfo.Invoke(), чтобы выполнить функцию через отражение. Вызов обернут в блок try/catch, но он все равно не поймает исключение, выданное вызываемой мной функцией.

Я получаю следующее сообщение:

Исключение не было обработано пользователем.


Почему MethodInfo.Invoke() препятствует тому, чтобы Исключение было поймано за пределами Invoke()?
Как мне обойти это?

Ответы [ 2 ]

28 голосов
/ 07 ноября 2010

РЕДАКТИРОВАТЬ: Как я понимаю вашу проблему, проблема чисто IDE; вам не нравится, когда VS рассматривает исключение, выброшенное вызовом MethodInfo, как необработанное, когда это явно не так. Вы можете прочитать о том, как решить эту проблему, здесь: Почему TargetInvocationException обрабатывается IDE как необнаруженное? Кажется, это ошибка / по замыслу; но так или иначе, достойные обходные пути перечислены в этом ответе.

На мой взгляд, у вас есть несколько вариантов:

  1. Вы можете использовать MethodInfo.Invoke, перехватить TargetInvocationException и проверить его InnerException свойство. Вам придется обойти проблемы IDE, как указано в этом ответе.

  2. Вы можете создать соответствующий Delegate из MethodInfo и вызвать его вместо этого. С этой техникой, выброшенное исключение не будет перенесено. Кроме того, этот подход действительно , кажется, хорошо работает с отладчиком; У меня нет всплывающих окон "Uncaught exception".

Вот пример, который выделяет оба подхода:

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();
    }
}
19 голосов
/ 07 ноября 2010

Как вы пытаетесь поймать исключение? Обычно то, что выбрасывается из вызова к Invoke(), является экземпляром исключения упаковки System.Reflection.TargetInvocationException. Фактическое исключение, за которым вы будете следовать, будет в InnerException.

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