Получить имя и тип свойства с помощью лямбда-выражения
Я пытаюсь написать функцию, которая будет извлекать имя свойства и тип с использованием синтаксиса, как показано ниже:
private class SomeClass
{
Public string Col1;
}
PropertyMapper<Somewhere> propertyMapper = new PropertyMapper<Somewhere>();
propertyMapper.MapProperty(x => x.Col1)
Есть ли способ передать свойство в функцию без каких-либо серьезных изменений в этом синтаксисе?
Я хотел бы получить имя свойства и тип свойства.
Так что в приведенном ниже примере я хотел бы получить
Name = "Col1"
а также Type = "System.String"
Кто-нибудь может помочь?
4 ответа
Вот достаточно примера использования выражений, чтобы получить имя свойства или поля, чтобы начать работу:
public static MemberInfo GetMemberInfo<T, U>(Expression<Func<T, U>> expression)
{
var member = expression.Body as MemberExpression;
if (member != null)
return member.Member;
throw new ArgumentException("Expression is not a member access", "expression");
}
Код вызова будет выглядеть так:
public class Program
{
public string Name
{
get { return "My Program"; }
}
static void Main()
{
MemberInfo member = ReflectionUtility.GetMemberInfo((Program p) => p.Name);
Console.WriteLine(member.Name);
}
}
Слово предостережения, хотя: простая оценка (Program p) => p.Name
на самом деле включает в себя довольно много работы (и может занять измеримое количество времени). Попробуйте кэшировать результат, а не вызывать метод часто.
Это легко сделать в C# 6. Для получения имени свойства используйте оператор name of.
nameof(User.UserId)
и для получения типа свойства используйте оператор type of.
typeof(User.UserId)
Я нашел это очень полезным.
public class PropertyMapper<T>
{
public virtual PropertyInfo PropertyInfo<U>(Expression<Func<T, U>> expression)
{
var member = expression.Body as MemberExpression;
if (member != null && member.Member is PropertyInfo)
return member.Member as PropertyInfo;
throw new ArgumentException("Expression is not a Property", "expression");
}
public virtual string PropertyName<U>(Expression<Func<T, U>> expression)
{
return PropertyInfo<U>(expression).Name;
}
public virtual Type PropertyType<U>(Expression<Func<T, U>> expression)
{
return PropertyInfo<U>(expression).PropertyType;
}
}
Я сделал этот маленький класс, чтобы следовать первоначальному запросу. Если вам нужно имя свойства, вы можете использовать его следующим образом:
PropertyMapper<SomeClass> propertyMapper = new PropertyMapper<SomeClass>();
string name = propertyMapper.PropertyName(x => x.Col1);
Я просто думал, что положу это здесь, чтобы основываться на предыдущем подходе.
public static class Helpers
{
public static string PropertyName<T>(Expression<Func<T>> expression)
{
var member = expression.Body as MemberExpression;
if (member != null && member.Member is PropertyInfo)
return member.Member.Name;
throw new ArgumentException("Expression is not a Property", "expression");
}
}
Затем вы можете назвать это следующим образом:
Helpers.PropertyName(() => TestModel.TestProperty);
Я также должен отметить, что с VS 2015 и C# 6.0 вы можете просто использовать nameof.