【问题标题】:trapping setter exception thrown by PropertyInfo.setvalue捕获由 PropertyInfo.setvalue 引发的 setter 异常
【发布时间】:2014-06-03 20:42:26
【问题描述】:

我有一种情况,即在来自 classA 的 PropertyInfo 上的 SetValue 周围放置一个 try-catch 不会捕获 classA 属性的设置器抛出的异常。我该如何陷害这个案子?示例如下:

  public class classA
{
    private string _ID;
    public string ID
    {
        get { return _ID; }
        set
        {
            if (_ID == null) _ID = value;
            else throw new InvalidOperationException();
        }

    }
}

public class classB
{
    public void DoMagic()
    {
        classA MyA = new classA();

        PropertyInfo pi = GetPropertyInfoForProperty(typeof(classA), "ID");
        try
        {
            pi.SetValue(MyA, "This works fine", null);
        }
        catch { }

        ///MyA.ID = "The first time you set it everything is cool.";

        try
        {
            MyA.ID = "This throws a handled exception.";
        }
        catch { }


        try
        {
            pi.SetValue(MyA, "This Throws and Unhandled Exception", null);
        }
        catch { }

    }

    private PropertyInfo GetPropertyInfoForProperty(Type type, string p)
    {
        foreach (var pi in type.GetProperties())
            if (pi.Name == p)
                return pi;
        return null;
    }


}

【问题讨论】:

  • 你能发布没有被捕获的异常细节吗?您是否看到诸如“调用目标抛出异常”之类的消息?顺便说一句,我无法在 LinqPad 中重现该问题。
  • 您是否确定 GetPropertyInfoForProperty() 方法没有抛出异常?第一次使用 SetValue 反射是否有效?
  • 请显示函数“GetPropertyInfoForProperty”的代码
  • 消息是 InvalidOperationException is unhandled by user code {"Operation is not valid due to the current state of the object."} 这是我故意抛出的异常。
  • 不是答案,但您可以将方法更改为 return type.GetProperty(p);

标签: c#


【解决方案1】:

查看代码后,我认为问题是classA 类的ID 设置器中的逻辑错误。目前的代码是:

public class classA
{
    private string _ID;
    public string ID
    {
        get { return _ID; }
        set
        {
            if (_ID == null) _ID = value;
            else throw new InvalidOperationException();
        }

    }
}

当 ID 接收到 null 以外的值时,上面的代码总是会抛出 InvalidOperationException。如果您第一次设置它,它将始终有效,但以后不会。我打算建议在您的 setter 中重新排列 if 语句,但后来我意识到您的意图可能是让 ID 属性只能设置一次,如下所示,但是当您尝试设置它时它会抛出相同的异常第一次,所以这行不通。

public class classA
{
    private string _ID;
    public string ID
    {
        get { return _ID; }
        set
        {
            // This will always throw an exception
            if (_ID == null) 
            {
                // Is this what you intended? 
                // That is, throw an InvalidOperationException if a null value is supplied?
                throw new InvalidOperationException();
            }

            _ID = value;
        }

    }
}

话虽如此,我仍然不清楚为什么 ID 应该只设置一次,假设我的理解是正确的,但是您可以尝试修改您的逻辑,以便通过构造函数设置 ID 并使 ID 设置器 @ 987654328@。不幸的是,这将迫使您修改您打算执行的其余代码。没有太多信息,这是我最好的答案。请注意,按照惯例,我会抛出 ArgumentException,但您也可以抛出 ArgumentNullException。我选择前者是因为我使用了String.IsNullOrWhiteSpace() 方法。

public class classA
{
    public string ID { get; private set; }

    public classA(string id)
    {
        if (String.IsNullOrWhiteSpace(id))
        {
            throw ArgumentException("id");
        }

        ID = id;
    }
}

【讨论】:

  • 目的是使 ID 只能设置一次 - 为此目的使用构造函数通常是我会做的,但是我需要将此对象序列化/反序列化为 XML,因此我需要一个默认构造函数。有一些解决方法可以避免抛出异常 - 但它仍然不能解释为什么我不能用 pi.SetValue() 周围的 try-catch 捕获异常,这是我问题的症结所在。我发布的代码只是这个问题可能出现的一个例子。我对大部分代码使用 try-catch 来捕获错误情况,以便记录它们。我在这里做不到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-13
  • 1970-01-01
  • 2014-10-07
  • 2011-04-19
  • 2017-03-22
相关资源
最近更新 更多