Получить имя и тип свойства, используя выражение лямбда

Я пытаюсь написать функцию, которая вытащит имя свойства и тип, используя синтаксис, как показано ниже:

private class SomeClass
{
    Public string Col1;
}

PropertyMapper<Somewhere> propertyMapper = new PropertyMapper<Somewhere>();
propertyMapper.MapProperty(x => x.Col1)

Есть ли способ передать свойство через функцию без каких-либо серьезных изменений в этом синтаксисе?

Я хотел бы получить имя свойства и тип свойства.

Итак, в приведенном ниже примере я хотел бы получить

Name = "Col1" и Type = "System.String"

Может ли кто-нибудь помочь?

Ответы

Ответ 1

Здесь достаточно примера использования Expressions, чтобы получить имя свойства или поля, чтобы вы начали:

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 фактически включает в себя довольно много работы (и может принимать измеримые количества времени). Рассмотрите кэширование результата, а не часто вызывайте метод.

Ответ 2

Я нашел это очень полезным.

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);

Ответ 3

Это легко сделать в С# 6. Чтобы получить имя свойства, используйте имя оператора.

nameof(User.UserId)

и получить тип свойства use typeof.

typeof(User.UserId)

Ответ 4

Я просто подумал, что я поставил бы это здесь, чтобы опираться на предыдущий подход.

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 и С# 6.0 вы можете просто использовать nameof.

https://msdn.microsoft.com/en-us/library/dn986596.aspx