Можно ли получить строку имени свойства объекта без создания экземпляра объекта?
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))
. Для этого мне нужно предоставить экземпляр объекта.
Теперь я хочу сделать тот же без, создав экземпляр.
Ответы
Ответ 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;
}
}