如果我从属性的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"
}
答案 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)
有两个选项,其中很多都很棒:
解析来自Exception.StackTrace
属性的get_Name()方法,正如Ashley和Mongus所描述的那样。当getter被内联时(这不太可能发生),这将失败,因为内联方法调用(显然)不会出现在堆栈跟踪中。
抛出包含该属性名称的特殊异常:
public string PropertyName
{
get { throw new PropertyException("PropertyName", "Ex message.");
}
然而,这也不是很好,因为你应该明确抛出这种类型的异常。因此,来自深度调用堆栈的失败必须包含在PropertyException
。
答案 3 :(得分:0)
如果你正在考虑这样的事情,你很可能会更好地实现INotifyPropertyChanged
之类的东西,并将其作为你的getter的一部分,而不是像正常使用一样关心setter。
答案 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
方法。