由PropertyInfo.setvalue抛出的trap setter异常

本文关键字:trap setter 异常 PropertyInfo setvalue | 更新日期: 2023-09-27 18:06:37

我有一种情况,在classA的PropertyInfo上放置SetValue周围的try-catch不会捕获由classA属性的setter抛出的异常。我如何捕捉这个案例?在下面的例子:

  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;
    }

}

由PropertyInfo.setvalue抛出的trap setter异常

在审查代码后,我认为问题是classA类的ID setter中的逻辑错误。当前代码是:

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 setter private。不幸的是,这将迫使您修改您打算执行的其余代码。没有太多信息,这是我最好的答案。请注意,按照惯例,我将抛出一个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;
    }
}