2

my question is similar to Using reflection, setter throws exception which can't be caught, but the recommended solution does not solve my problem.

In the code below, I try to set the property of a class via two different ways: first, directly and second, via reflection. The setter throws an exception (in the real use case only if the given value is invalid) that should be caught at the place where the setter is called. But the exception is only caught in the first variant; in the second, the catch-block is never executed. What is the reason for this?

In my use case, I want to use the reflection variant but the program always terminates where the exception is thrown and I have no change to catch it.

The mentioned thread above recommends that either the Debugger is configured in such a way that it breaks at every exception (this cannot be the case as in the first variant, the exception is caught perfectly fine) or that the exception comes from somewhere else. Unfortunately, I do not know where it could come from otherwise.

Thank you very much for your help!

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");
            }
        }
    }
}
  • 3
    Can't reproduce. https://dotnetfiddle.net/l0KWnO. Just add some meaningful string before your `e.Message` in the second case. Otherwise the text is surely just the error-message. Anyway your exception is wrapped within a `TargetInvocationException`, which is normal for reflection-calls. However it **is** caught. – MakePeaceGreatAgain Jan 22 '20 at 14:59
  • Thank you. You are right. It seemed to me (on dotnetfiddle) the exception was not caught because I forgot to add some text in the console output. So, on dotnetfiddle, I am content :) However, in Visual Studio, I still have the same problem as in the beginning. The first exception (when the setter is called directly) is being caught, but in the second (via reflection), VS jumps to the place where the exception is thrown and says that the exception is unhandled by the user. How can this be solved? – Matthias Heinlein Jan 23 '20 at 12:17
  • Did you step through and see if the `catch` is not hit? Put a breakpoint into the `catch` and see. I guess it´s just the debugger that tells you there occurs an excption. It doesn´t know that you catch that exception later on. – MakePeaceGreatAgain Jan 23 '20 at 12:44
  • I think I found an answer to my question: As in [link](https://stackoverflow.com/questions/2658908/why-is-targetinvocationexception-treated-as-uncaught-by-the-ide) mentioned, I had "Just my code" enabled and as Exception is thrown in a reflection function, it leaves my code for a moment before it returns to my code where I want to catch it. So, disabling this option solves the problem in my case. – Matthias Heinlein Jan 23 '20 at 12:52
  • @HimBromBeere I tried to put a breakpoint there and it did not help. But see my previous comment. I think this is the reason for the problem - hard to find. – Matthias Heinlein Jan 23 '20 at 12:54

2 Answers2

1

Using the comments of @Lutti Coelho and @HimBromBeere and this thread I found the solution to my problem:

1) My assumption that the second exception (thrown in the reflection call) is not caught, was wrong. It is caught, but my Console output did not show it correctly.

2) Every exception thrown in a SetValue() (oder GetValue()) reflection call is wrapped inside a TargetInvocationException e. The real exception is e.InnerException. This is important if you throw a user-defined exception and write a catch-clause for this specific exception type.

Understanding these two things, the code ran as desired on dotnetfiddle. However, in Visual Studio the Debugger still terminated at the point where the exception was thrown telling me that the exception was unhandled even though I put a try-catch-block around the reflection call.

3) Here, the mentioned thread helped me: Visual Studio has a setting called "Just my Code" (see Tools → Options → Debugging → General → Enable Just My Code). If enabled, it halts at every exception that is not handled in my code. In my case, my code threw the exception, but it left my code going through the C# standard reflection library and only returned to my code later. As the exception was unhandled at the point where it left my code, the debugger terminated at this point. So, disabling this setting in Visual Studio solved my problem in the end.

0

Your exception was throwed. But as it happens inside the SetValue method. The exception is inside the InnerException. To get your specific exception you need to call e.InnerException.

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

In resume, your Exception e is the exception rised by SetValue method. As is was rised because of another exception, the other exception is the InnerException.

You can see a working exaple in: https://dotnetfiddle.net/i49ZQC

Lutti Coelho
  • 2,134
  • 15
  • 31
  • Thank you! I did not know that there is another exception around it. However, in Visual Studio, I still have the same problem (see my comment regarding the post of @HimBromBeere). – Matthias Heinlein Jan 23 '20 at 12:19
  • Sorry. I just see your comment now. I saw HimBromBeere's messages and yours on the question comments and I undestand you solved your problem rigth? – Lutti Coelho Jan 23 '20 at 14:37
  • Yes, thank you! I am just not sure how we can make this question and answer accessible for other people having a similar issue. I learned two important things: first, that an exception thrown in a reflection function call is wrapped inside another exception, and second, that Visual Studio has to be configured correctly to be able to catch the exception. I am quite new to Stackoverflow: should I edit the question and include the Visual Studio problem and then write an answer by myself? – Matthias Heinlein Jan 23 '20 at 18:43
  • I believe your question has enough info about your problem. I just recommend you to answer your question with your discovery. I'll be glad to up vote it. – Lutti Coelho Jan 23 '20 at 19:12