能否在不创建对象实例的情况下获取对象属性名称字符串?

16

可以使用Expression<Func<T>>获取一个对象实例属性的字符串表示形式:

string propertyName = ((MemberExpression) property.Body).Member.Name;

如果我没有(或者不想创建)实例,怎么办?在这种情况下,我该如何获取属性名?

解释

我需要一个对象某个属性名称的字符串表示。

假设有一个实体:

public class Customer
{
    public int ID;
    public string Name;
}

现在我想将此实体的键表达式传递给其他函数,因此我需要字符串“ID”,但我不想像 SomeOtherFunction("ID") 那样硬编码字符串,而是使用表达式 SomeOtherFunction(ExpressionReader.GetString(() => CustomerInstance.ID))。为了使其正常工作,我需要提供实体实例。

现在我想做同样的事情,而无需创建实例


“实例”是什么意思?你不需要创建公开该属性的类的实例,但显然你需要一个Expression<T>的实例。 - CodesInChaos
你知道 typeof(myClass).GetProperty("abc") 这个吗? - Efrain
硬编码ID属性和"ID"字符串有什么区别? - SWeko
1
@SWeko 当需要将属性名称“ID”更改为“NewId”时,Visual Studio会在所有引用的位置自动完成此操作 :-) - 也许还有其他原因。 - Michał Powaga
可能是使用lambda表达式获取属性名称和类型的重复问题。 - nawfal
5个回答

17

可以通过以下方法签名实现:

private static string GetPropertyName<TModel, TProperty>(Expression<Func<TModel, TProperty>> property)
{
    MemberExpression memberExpression = (MemberExpression)property.Body;

    return memberExpression.Member.Name;
}
您可以在不使用客户类的实例的情况下调用此方法:
string propertyName = GetPropertyName((Customer c) => c.ID);

在将表达式转换为 MemberExpression 并访问 memberExpression.Member.Name 之前,当然应该添加一些检查以确保表达式类型正确。


4
不需要实例来分解表达式。即使表达式期望一个实例,你也永远不会调用它。实际上,你只需要像第一个代码片段一样做就行了。然后你需要修改你的代码看起来像这样:
SomeOtherFunction(ExpressionReader<Customer>.GetString(c => c.ID))

你理解我的意思吗?

或者:

Customer c = null; // null intentionally

SomeOtherFunction(ExpressionReader.GetString(() => c.ID));

只要您不调用表达式,就没有问题。


@net_prog:你需要修改你的代码,这只是一个可能的建议,还有很多其他可能性。 - leppie

3

使用C# 6的新 nameof 运算符,建议以下操作:

 private string GetNameMyProperty1(TestC c = null)
 {
     return nameof(c.MyProperty1);
 }

4
你甚至不需要对象的实例,只需像这样执行 nameof(TestC.MyProperty1) - jausel

1

我不确定我完全理解你的意思,但根据我的理解,你可以使用反射。使用这种方法,如果你有想要获取属性名称的Type,那么你可以使用以下代码检索属性:

Type someType = typeof(SomeClass);

// Get all properties for a type
PropertyInfo[] properties = someType.GetProperties();

// Get a property from a type by it's name
PropertyInfo property = someType.GetProperty("PropertyName");

一旦您拥有PropertyInfo类的实例,您可以检索诸如属性名称之类的信息。

有关此方法的更多信息,请参见MSDN文档


0

所选答案不错,但未涵盖UnaryExpressions。当尝试获取DateTime属性时,它将失败:

    private static string GetPropertyName<TModel, TProperty>(Expression<Func<TModel, TProperty>> property)
    {
        if (property.Body is MemberExpression)
        {
            return ((MemberExpression)property.Body).Member.Name;
        }
        else
        {
            var op = ((UnaryExpression)property.Body).Operand;
            return ((MemberExpression)op).Member.Name;
        }  
    }

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