如何使用反射获取C#属性名称的字符串?

7
我希望能够获取属性的名称作为字符串,这样我就可以拥有一个“强类型”的魔法字符串。我需要做的是像 MyClass.SomeProperty.GetName() 这样的事情,它将返回“SomeProperty”。在C#中是否可能实现?
3个回答

9
这种方法比使用Expression要快得多。
public static string GetName<T>(this T item) where T : class
{
    if (item == null)
        return string.Empty;

    return typeof(T).GetProperties()[0].Name;
}

现在你可以调用它:
new { MyClass.SomeProperty }.GetName();

如果您需要更好的性能,可以缓存值。请参阅此重复问题如何获取变量的名称,就像在其声明中实际键入的那样?


最佳答案在此处。我不想循环属性,我想根据实际属性获取属性名称。使用第一个(唯一)属性为您想要名称的匿名类型是天才。 - Paul
@Paul 我并不是它背后的天才。其次,它不太适应重构。我的意思是,如果你更改属性的名称,匿名类型会保留原始名称。在这种情况下,如果您将“SomeProperty”更改为“SomeProperty1”,则匿名类会更改为“new { SomeProperty = SomeProperty1 }”,而不是更新后的名称“SomeProperty1”。我会在答案中提到这一点。 - nawfal
糟糕。我不预计会更改属性名称,但如果我真的这样做了,我希望重构能够处理它。谢谢你让我知道。 - Paul
如果在执行时 MyClass 为空,这也会失败。表达式方法将成功。在绝大多数情况下,这不会成为问题,因为你会在其他地方得到空引用异常,但是值得指出。 - Rakuen42
@Pedro77,首先你需要在一个静态类中编写这个扩展方法。 - nawfal

7
你可以使用表达式来轻松实现这一点。请参阅此博客示例
这样,您可以通过lambda创建一个表达式,并提取名称。例如,实现INotifyPropertyChanged可以重新设计为执行以下操作:
public int MyProperty {
    get { return myProperty; }
    set
    {
        myProperty = value;
        RaisePropertyChanged( () => MyProperty );
    }
}

为了映射您的等效值,使用参考的“Reflect”类,您需要执行以下操作:
string propertyName = Reflect.GetProperty(() => SomeProperty).Name;

Viola - 不需要神奇字符串的属性名称。


这里的语法有点糟糕,但它确实做到了我需要的事情。谢谢! - Jim Mitchener

2
您可以使用反射来获取对象的属性列表。
MyClass o;

PropertyInfo[] properties = o.GetType().GetProperties(
    BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance
);

每个属性都有一个名称属性,它可以获取到“SomeProperty”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接