【问题标题】:Using reflection, setter throws exception which can't be caught使用反射,setter 抛出无法捕获的异常
【发布时间】:2014-06-25 20:41:46
【问题描述】:

我正在使用反射来设置对象的属性。如果任何 setter 抛出异常,则进行 SetValue 调用的代码不会捕获该异常。 Visual Studio 告诉我该异常未被用户代码捕获。

例如,假设在下面的示例中,“target”变量引用的对象的 Title 属性设置器会抛出 ArgumentException

看调用栈,好像下面的sn-p和setter之间有非托管代码。

谁能解释一下(&谢谢!):

  • 首先为什么会发生这种情况?
  • 有没有不重新考虑程序逻辑的简单方法来修复它?

这是我的代码:

try
{
    prop.SetValue(target, attr.Value); // target does have a "Title" property
                                       // attr.Value == "Title"
                                       // the setter throws an ArgumentException

}
catch (Exception ex) // No exception is ever caught.
{
    errors.Add(ex.Message);
}

下面是我想要设置的众多属性之一的代码: 公共字符串标题 { 得到 { 返回这个.title; }

        set
        {
            if (string.IsNullOrEmpty(value) || value.Length < 1 || value.Length > 128)
            {
                throw new ArgumentException("Title must be at least 1 character and cannot be longer than 128 characters.");
            }

            this.title = value;
        }
    }

【问题讨论】:

  • 然后显示此 Title 属性代码...
  • SSCCE 会有所帮助。 sscce.org
  • 另外,您不应假设已填充 InnerException。可能是null。使用ex.ToString() 获取“异常类型希望您看到的所有内容,包括内部异常”
  • 请在此处解释为什么要使用反射
  • 您确定这不仅仅是调试器设置为停止所有异常,无论它们是否由用户处理? ArgumentException 告诉你什么?

标签: c# reflection


【解决方案1】:

EDIT 如@Default 所述,Framework 4.5 确实有一个只有两个参数的重载,所以如果用户使用 FW 4.5 这个答案没有相关性(至少最后一部分是关于属性信息),

你错了,它被困住了,这里有一个例子来证明它:

public class ExceptionGenerator
{
    public static void Do()
    {

        ClassToSet clas = new ClassToSet();

        Type t = clas.GetType();

        PropertyInfo pInfo = t.GetProperty("Title");

        try
        {

            pInfo.SetValue(clas, "test", null);
        }
        catch (Exception Ex)
        {

            Debug.Print("Trapped");

        }
    }
}

class ClassToSet
{

    public string Title {

        set {

            throw new ArgumentException();

        }

    }

}

您做错的是获取 PropertyInfo,PropertiInfo 的 SetValue 方法需要第三个参数,即属性索引(在您的情况下为 null),因此您的“prop”不是 PropertyInfo,我假设它是 FieldInfo,并且因为它会引发未处理的异常。

【讨论】:

  • PropertyInfo 肯定有一个带有 2 个参数的 .SetValue() 重载
  • this SetValue 接受两个参数。
  • 仅在 FW 4.5 上...我仍在使用 FW 4.0 :S,但如果用户未使用 FW 4.5,则答案是正确的。
【解决方案2】:

任何异常都应该被捕获。

见小提琴:https://dotnetfiddle.net/koUv4j

这包括反射调用本身的错误(将属性设置为错误的Type),或者属性的设置器本身存在异常(set 抛出)。

这会导致其他问题。可能性:

  • 您已将 IDE 设置为在所有异常情况下停止
  • 异常并未发生在您认为的位置(例如,在catch 中,它将重新throw

如果不是这两个之一,请提供更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-09
    • 2021-09-02
    • 2011-04-05
    • 2015-09-23
    • 2013-08-02
    • 2018-05-30
    • 2019-08-30
    • 1970-01-01
    相关资源
    最近更新 更多