C# - 在 属性 setter 中抛出的异常在通过反射 (SetValue()) 调用时无法捕获
C# - Exception thrown in property setter cannot be caught when called via reflection (SetValue())
我的问题与Using reflection, setter throws exception which can't be caught类似,但是推荐的方案没有解决我的问题。
在下面的代码中,我尝试通过两种不同的方式设置 class 的 属性:第一种,直接,第二种,通过反射。 setter 抛出异常(在实际用例中,仅当给定值无效时)应在调用 setter 的地方捕获。
但是异常只在第一个变体中被捕获;
在第二个中,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");
}
}
}
}
您的异常被抛出。但是因为它发生在 SetValue
方法内部。异常在 InnerException
内。要获得特定的异常,您需要调用 e.InnerException
.
catch (Exception e)
{
Console.WriteLine("Reflection exception was caught: " + e.InnerException.Message);
}
在简历中,您的 Exception e
是由 SetValue
方法引发的异常。由于另一个异常而上升,另一个异常是 InnerException
.
您可以在以下位置查看工作示例:https://dotnetfiddle.net/i49ZQC
使用@Lutti Coelho 和@HimBromBeere 的评论以及这个 thread 我找到了解决问题的方法:
1) 我假设第二个异常(在反射调用中抛出)没有被捕获,这是错误的。它被捕获了,但我的控制台输出没有正确显示它。
2) SetValue()(或 GetValue())反射调用中抛出的每个异常都包含在 TargetInvocationException e 中。真正的例外是 e.InnerException。如果您抛出用户定义的异常并为此特定异常类型编写 catch 子句,这一点很重要。
明白了这两点,代码运行就如愿上了dotnetfiddle。然而,在 Visual Studio 中,调试器仍然在抛出异常的地方终止,告诉我异常未处理,即使我在反射调用周围放置了一个 try-catch-block。
3) 在这里,提到的 thread 帮助了我:Visual Studio 有一个名为 "Just my Code" 的设置(请参阅工具 → 选项 → 调试 → 常规 → 仅启用我的代码)。如果启用,它会在我的代码中未处理的每个异常时停止。在我的例子中,我的代码抛出了异常,但它让我的代码通过 C# 标准反射库并且稍后才返回到我的代码。由于异常在它离开我的代码时未得到处理,因此调试器在此时终止。
因此,在 Visual Studio 中禁用此设置最终解决了我的问题。
我的问题与Using reflection, setter throws exception which can't be caught类似,但是推荐的方案没有解决我的问题。
在下面的代码中,我尝试通过两种不同的方式设置 class 的 属性:第一种,直接,第二种,通过反射。 setter 抛出异常(在实际用例中,仅当给定值无效时)应在调用 setter 的地方捕获。 但是异常只在第一个变体中被捕获; 在第二个中,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");
}
}
}
}
您的异常被抛出。但是因为它发生在 SetValue
方法内部。异常在 InnerException
内。要获得特定的异常,您需要调用 e.InnerException
.
catch (Exception e)
{
Console.WriteLine("Reflection exception was caught: " + e.InnerException.Message);
}
在简历中,您的 Exception e
是由 SetValue
方法引发的异常。由于另一个异常而上升,另一个异常是 InnerException
.
您可以在以下位置查看工作示例:https://dotnetfiddle.net/i49ZQC
使用@Lutti Coelho 和@HimBromBeere 的评论以及这个 thread 我找到了解决问题的方法:
1) 我假设第二个异常(在反射调用中抛出)没有被捕获,这是错误的。它被捕获了,但我的控制台输出没有正确显示它。
2) SetValue()(或 GetValue())反射调用中抛出的每个异常都包含在 TargetInvocationException e 中。真正的例外是 e.InnerException。如果您抛出用户定义的异常并为此特定异常类型编写 catch 子句,这一点很重要。
明白了这两点,代码运行就如愿上了dotnetfiddle。然而,在 Visual Studio 中,调试器仍然在抛出异常的地方终止,告诉我异常未处理,即使我在反射调用周围放置了一个 try-catch-block。
3) 在这里,提到的 thread 帮助了我:Visual Studio 有一个名为 "Just my Code" 的设置(请参阅工具 → 选项 → 调试 → 常规 → 仅启用我的代码)。如果启用,它会在我的代码中未处理的每个异常时停止。在我的例子中,我的代码抛出了异常,但它让我的代码通过 C# 标准反射库并且稍后才返回到我的代码。由于异常在它离开我的代码时未得到处理,因此调试器在此时终止。 因此,在 Visual Studio 中禁用此设置最终解决了我的问题。