C# - Исключение, генерируемое в установщике свойств, не может быть перехвачено при вызове через отражение (SetValue ()) - PullRequest
2 голосов
/ 22 января 2020

мой вопрос похож на Используя отражение, сеттер генерирует исключение, которое не может быть поймано , но рекомендуемое решение не решает мою проблему.

В приведенном ниже коде я пытаюсь установить свойство класса двумя различными способами: первым, прямым и вторым, через отражение. Сеттер генерирует исключение (в реальном случае, только если данное значение недопустимо), которое должно быть перехвачено в том месте, где вызывается сеттер. Но исключение поймано только в первом варианте; во втором блоке catch никогда не выполняется. В чем причина этого?

В моем случае я хочу использовать вариант отражения, но программа всегда завершает работу, когда выбрасывается исключение, и у меня нет изменений, чтобы его перехватить.

Упомянутый выше поток рекомендует, чтобы либо отладчик был настроен таким образом, чтобы он ломался при каждом исключении (это не может быть так, как в первом варианте, исключение ловится совершенно нормально), или что исключение происходит откуда-то еще. К сожалению, я не знаю, откуда это могло прийти.

Большое спасибо за вашу помощь!

using System;
using System.Reflection;

namespace ReflectionTestConsole
{
    public class Program
    {
        public static void Main(string[] args)
        {

            Logic logic = new Logic();
            try
            {
                logic.MyProperty = 5;
            } 
            catch(Exception e)
            {   // in this case, the exception is caught here.
                Console.WriteLine("Exception was caught: " + e.Message);
            }

            try{
                PropertyInfo propInfo = logic.GetType().GetProperty("MyProperty");
                propInfo.SetValue(logic,5);
            }
            catch (Exception e)
            {   // in this case, the exception is not caught
                Console.WriteLine(e.Message);
            }

        }
    }

    public class Logic
    {
        private double variable;
        public double MyProperty
        {
            get
            {
                return variable;
            }
            set
            { //Check if value is valid and if not throw an exception
                throw new Exception("This is the exception");
            }
        }
    }
}

Ответы [ 2 ]

1 голос
/ 27 января 2020

Используя комментарии @Lutti Coelho и @HimBromBeere и этой темы Я нашел решение своей проблемы:

1) Мое предположение, что второе исключение (выброшенное в отражении, вызывает ) не пойман, был не прав. Он перехвачен, но мой вывод консоли не показал его правильно.

2) Каждое исключение, выброшенное в вызове отражения SetValue () (oder GetValue ()), заключено в исключение TargetInvocationException e. Настоящим исключением является e.InnerException. Это важно, если вы сгенерируете пользовательское исключение и напишите предложение catch для этого указанного c типа исключения.

Понимая эти две вещи, код запускается в соответствии с желаниями на dotnetfiddle. Однако в Visual Studio отладчик по-прежнему завершал работу в том месте, где было сгенерировано исключение, сообщая мне, что исключение не было обработано, даже если я поместил блок try-catch вокруг вызова отражения.

3) Здесь упомянутый поток помог мне: в Visual Studio есть настройка под названием «Просто мой код» (см. Инструменты → Параметры → Отладка → Общие → Включить только мой код). Если он включен, он останавливается при каждом исключении, которое не обрабатывается в моем коде. В моем случае мой код выдал исключение, но он оставил мой код через стандартную библиотеку отражений C# и вернулся к моему коду позже. Поскольку исключение не было обработано в том месте, где он оставил мой код, отладчик завершился в этот момент. Итак, отключение этого параметра в Visual Studio решило мою проблему в итоге.

0 голосов
/ 22 января 2020

Ваше исключение было брошено. Но как это происходит внутри метода SetValue. Исключение находится внутри InnerException. Чтобы получить указанное вами c исключение, вам нужно вызвать e.InnerException.

    catch (Exception e)
    {   
        Console.WriteLine("Reflection exception was caught: " + e.InnerException.Message);
    }

В резюме ваше Exception e - это исключение, вызванное методом SetValue. Как и было поднято из-за другого исключения, другое исключение - InnerException.

Вы можете увидеть рабочий пример в: https://dotnetfiddle.net/i49ZQC

...