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

IntelliJ IDEA 2018.1.4 (Ultimate Edition), построенный 16 мая 2018 года

477
задан casperOne 5 January 2011 в 16:18
поделиться

7 ответов

Я нашел другой способ, которым вы можете сделать, это строго указать тип источника и свойства и явно сделать вывод для лямбда-выражения. Не уверен, что это правильная терминология, но вот результат.

public static RouteValueDictionary GetInfo<T,P>(this HtmlHelper html, Expression<Func<T, P>> action) where T : class
{
    var expression = (MemberExpression)action.Body;
    string name = expression.Member.Name;

    return GetInfo(html, name);
}

А потом назовите это так.

GetInfo((User u) => u.UserId);

и вуаля это работает.
Спасибо всем.

180
ответ дан Mark Hurd 5 January 2011 в 16:18
поделиться

Начиная с .NET 4.0 вы можете использовать ExpressionVisitor , чтобы найти свойства:

class ExprVisitor : ExpressionVisitor {
    public bool IsFound { get; private set; }
    public string MemberName { get; private set; }
    public Type MemberType { get; private set; }
    protected override Expression VisitMember(MemberExpression node) {
        if (!IsFound && node.Member.MemberType == MemberTypes.Property) {
            IsFound = true;
            MemberName = node.Member.Name;
            MemberType = node.Type;
        }
        return base.VisitMember(node);
    }
}

Вот как вы используете этого посетителя:

var visitor = new ExprVisitor();
visitor.Visit(expr);
if (visitor.IsFound) {
    Console.WriteLine("First property in the expression tree: Name={0}, Type={1}", visitor.MemberName, visitor.MemberType.FullName);
} else {
    Console.WriteLine("No properties found.");
}
1
ответ дан dasblinkenlight 5 January 2011 в 16:18
поделиться

Я создал метод расширения для ObjectStateEntry, чтобы иметь возможность помечать свойства (классов POCO Entity Framework) как модифицированные безопасным способом, поскольку метод по умолчанию принимает только строку. Вот мой способ получить имя от собственности:

public static void SetModifiedProperty<T>(this System.Data.Objects.ObjectStateEntry state, Expression<Func<T>> action)
{
    var body = (MemberExpression)action.Body;
    string propertyName = body.Member.Name;

    state.SetModifiedProperty(propertyName);
}
3
ответ дан Anders 5 January 2011 в 16:18
поделиться

Ну, нет никакой потребности звонить .Name.ToString(), но широко который является об этом, да. Единственное соображение, в котором Вы, возможно, нуждались бы, состоит в том, должен ли x.Foo.Bar возвратить "Нечто", "Панель" или исключение - т.е. сделать необходимо выполнить итерации вообще.

(комментарий ре) для больше на гибкой сортировке, см. здесь .

5
ответ дан Marc Gravell 6 January 2011 в 02:18
поделиться

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

Вот метод, это возвратит объект PropertyInfo для выражения. Это выдает исключение, если выражение не является свойством.

public PropertyInfo GetPropertyInfo<TSource, TProperty>(
    TSource source,
    Expression<Func<TSource, TProperty>> propertyLambda)
{
    Type type = typeof(TSource);

    MemberExpression member = propertyLambda.Body as MemberExpression;
    if (member == null)
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a method, not a property.",
            propertyLambda.ToString()));

    PropertyInfo propInfo = member.Member as PropertyInfo;
    if (propInfo == null)
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a field, not a property.",
            propertyLambda.ToString()));

    if (type != propInfo.ReflectedType &&
        !type.IsSubclassOf(propInfo.ReflectedType))
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a property that is not from type {1}.",
            propertyLambda.ToString(),
            type));

    return propInfo;
}

source параметр используется так, компилятор может сделать вывод типа на вызове метода. Можно сделать следующий

var propertyInfo = GetPropertyInfo(someUserObject, u => u.UserID);
330
ответ дан Massimiliano Kraus 6 January 2011 в 02:18
поделиться
static void Main(string[] args)
{
    var prop = GetPropertyInfo<MyDto>(_ => _.MyProperty);

    MyDto dto = new MyDto();
    dto.MyProperty = 666;

    var value = prop.GetValue(dto);
    // value == 666
}

class MyDto
{
    public int MyProperty { get; set; }
}

public static PropertyInfo GetPropertyInfo<TSource>(Expression<Func<TSource, object>> propertyLambda)
{
    Type type = typeof(TSource);

    var member = propertyLambda.Body as MemberExpression;
    if (member == null)
    {
        var unary = propertyLambda.Body as UnaryExpression;
        if (unary != null)
        {
            member = unary.Operand as MemberExpression;
        }
    }
    if (member == null)
    {
        throw new ArgumentException(string.Format("Expression '{0}' refers to a method, not a property.",
            propertyLambda.ToString()));
    }

    var propInfo = member.Member as PropertyInfo;
    if (propInfo == null)
    {
        throw new ArgumentException(string.Format("Expression '{0}' refers to a field, not a property.",
            propertyLambda.ToString()));
    }

    if (type != propInfo.ReflectedType && !type.IsSubclassOf(propInfo.ReflectedType))
    {
        throw new ArgumentException(string.Format("Expression '{0}' refers to a property that is not from type {1}.",
            propertyLambda.ToString(), type));
    }

    return propInfo;
}
0
ответ дан 22 November 2019 в 22:43
поделиться

Я играл с тем же самым и придумал вот это. Он не полностью протестирован, но, похоже, решает проблему с типами значений (проблема с неарифметическим выражением, с которой вы столкнулись)

public static string GetName(Expression<Func<object>> exp)
{
    MemberExpression body = exp.Body as MemberExpression;

    if (body == null) {
       UnaryExpression ubody = (UnaryExpression)exp.Body;
       body = ubody.Operand as MemberExpression;
    }

    return body.Member.Name;
}
142
ответ дан 22 November 2019 в 22:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: