Можно ли получить строку имени свойства объекта без создания экземпляра объекта? - программирование
Подтвердить что ты не робот

Можно ли получить строку имени свойства объекта без создания экземпляра объекта?

A строковое представление свойства экземпляра объекта можно взять с помощью 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)). Для этого мне нужно предоставить экземпляр объекта.

Теперь я хочу сделать тот же без, создав экземпляр.

4b9b3361

Ответ 1

Это возможно с помощью сигнатуры метода, например:

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.

Ответ 2

Нет, вам не нужен экземпляр для разложения Expression. Даже если выражение ожидает одно, вы никогда его не вызовете.

Фактически, вы делаете это так же, как в первом фрагменте кода.

Вы изменили бы ваш код, чтобы выглядеть следующим образом:

SomeOtherFunction(ExpressionReader<Customer>.GetString(c => c.ID))

Это имеет смысл для вас?

В качестве альтернативы:

Customer c = null; // null intentionally

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

По-прежнему не проблема, поскольку вы не вызываете выражение.

Ответ 3

С новым оператором nameof на С# 6 я бы предложил следующее:

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

Ответ 4

Я не уверен, что полностью понимаю, что вы имеете в виду, но, основываясь на моем понимании, вы можете использовать Reflection. Используя этот подход, если у вас есть Type того, из чего вы хотите получить имя свойства, вы можете получить свойства, используя:

Type someType = typeof(SomeClass);

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

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

Как только у вас есть экземпляр класса PropertyInfo, вы можете получить информацию, такую ​​как имя свойства.

Дополнительную информацию об этом подходе см. в документации MSDN.

Ответ 5

Выбранный ответ хорош, но не охватывает 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;
        }  
    }