How to get the name of the property to which a lambda expression refers?

4

I have a lambda expression being translated into an expression tree, as follows:

Expression<Func<object>> expr = () => x.NomeDaPropriedade;

How do I get the name of the property, which in this case is NomeDaPropriedade , from this expression tree?

    
asked by anonymous 31.01.2014 / 14:36

4 answers

3

This function tries to retrieve the name by casting it as MemberExpression, if it does not work it does it by UnaryExpression.

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;
}
    
31.01.2014 / 14:56
3
public string AnalizarPropriedade<T>(Expression<T> expr)
{
    var memberExpr = expr.Body as UnaryExpression; // parse da expressao "x.y"
    var operand = memberExpr.Operand as MemberExpression; // parse do operando "y"
    return operand.Member.Name; // parse do nome do operando "y"
}

Unit test:

[Fact]
public void AnaliseDeExpressao_Retorna_NomeDaPropriedade()
{
    //com closure
    string str = "ola";
    Expression<Func<object>> expr = () => str.Length;
    Assert.Equal("Length", AnalizarPropriedade(expr));

    //sem closure
    Expression<Func<string, object>> expr2 = s => s.Length;
    Assert.Equal("Length", AnalizarPropriedade(expr2));
}
    
31.01.2014 / 14:50
2

You can take ownership of the lambda body maybe the method below will solve ...

public String ObterNome<T> (Expression<Func<T, object>> expressao)
{
        var lambda = (LambdaExpression) expressao;

        MemberExpression memberExpression;
        if (lambda.Body is UnaryExpression) {
            var unaryExpression = (UnaryExpression) lambda.Body;
            memberExpression = (MemberExpression) unaryExpression.Operand;
        }
        else {
            memberExpression = (MemberExpression) lambda.Body;
        }

        var member = memberExpression.Member;

        if( member == null ) return null;
        return member.Name;
}

use is like this

string nomePropriedade = ObterNomePropriedade<Pessoa>( x => x.Endereco );
    
31.01.2014 / 14:54
0

Well, just to summarize the answers already given, and based on them, I've created two helper methods to help with this task when needed, depending on the lambda format used:

public String ObterNome<TIn>(Expression<Func<TIn, object>> expression)
{
    return ObterNome(expression as Expression);
}

public String ObterNome<TOut>(Expression<Func<TOut>> expression)
{
    return ObterNome(expression as Expression);
}

private String ObterNome(Expression expression)
{
    var lambda = expression as LambdaExpression;
    var member = lambda.Body.NodeType == ExpressionType.Convert
                        ? ((UnaryExpression)lambda.Body).Operand as MemberExpression
                        : lambda.Body as MemberExpression;
    return member.Member.Name;
}

There is a method to get the name, if you use a lambda with closure, which points to the property, and another one in case there is no closure, but need to indicate the generic parameter type.

    
31.01.2014 / 15:13