如果我在属性的getter中抛出异常,我可以在catch块中获取属性的名称吗?

时间:2011-08-24 13:06:03

标签: c# .net reflection exception-handling stack-trace

如果我从属性的getter中抛出异常,是否可以获取

的名称

catch块中的属性,我使用反射或

调用该属性

读取堆栈跟踪?

例如:

class Animal
{
  private string _name;
  public string Name {

           get { throw new Exception(); } 

           set { _name = value; }
                     }
}

在另一个地方,我调用了Name属性的getter,我想获取catch块中的属性名称:

Animal cat = new Animal();

try{ 
    string catName = cat.Name;
   }

catch (Exception e)
   {

    string propertyName = //Here I should be able to reach "Name"  

   }

6 个答案:

答案 0 :(得分:0)

它将在您的堆栈跟踪中显示为get_Name()方法中的异常。您可以解析它以获取属性名称

答案 1 :(得分:0)

您可以使用正则表达式解析e.StackTrace

    try
    {
            int x = this.Ong;
    }
    catch ( Exception ex )
    {
            Console.WriteLine ( Regex.Match ( ex.StackTrace, @"get_(?<prop>.*)\(\)" ).Groups["prop"].Value );
    }

注意您应该对上面的Regex进行更多错误检查,因为Groups["prop"]如果未从属性引发异常,则可能为null。

答案 2 :(得分:0)

有两个选项,其中很多都很棒:

  1. 解析来自Exception.StackTrace属性的get_Name()方法,正如Ashley和Mongus所描述的那样。当getter被内联时(这不太可能发生),这将失败,因为内联方法调用(显然)不会出现在堆栈跟踪中。

  2. 抛出包含该属性名称的特殊异常:

    public string PropertyName
    {
        get { throw new PropertyException("PropertyName", "Ex message.");
    } 
    

    然而,这也不是很好,因为你应该明确抛出这种类型的异常。因此,来自深度调用堆栈的失败必须包含在PropertyException

答案 3 :(得分:0)

如果你正在考虑这样的事情,你很可能会更好地实现INotifyPropertyChanged之类的东西,并将其作为你的getter的一部分,而不是像正常使用一样关心setter。

How to: Implement the INotifyPropertyChanged Interface

答案 4 :(得分:0)

答案 5 :(得分:0)

从C#5开始,您可以使用CallerMemberNameAttribute

public class SomeCustomException : Exception
{
    public string PropertyName { get; }

    public SomeCustomException(string propertyName) 
        : base($"Property {propertyName} was null)
    {
        this.PropertyName = propertyName;
    }
}

public class Animal
{
    public string Name
    {
        get { Throw(); }
    }

    private static void Throw([CallerMemberName] string propertyName = null)
    {
        // propertyName will be 'Name'
        throw new CustomException(propertyName);
    }
}

我可以将[CallerMemberName]直接放在SomeCustomException的构造函数上,但这看起来不必要的丑陋:异常doens需要知道它将从属性getter中调用,因此单独的静态Throw方法。