Usando la expresión lambda para obtener la propiedad O escriba el nombre

c# expression-trees lambda

Pregunta

¿Cómo puedo adaptar el siguiente método para que funcione cuando la expresión lambda se refiere a la instancia real?

por ejemplo, en lugar de

x => x.Name

la expresión es

x => x

así que si tuviera alguna clase de "Car" podría devolver la cadena "Car" en lugar de solo poder operar en sus propiedades (por ejemplo, Car.Colour)

El método:

public static string GetMemberName(Expression expression)
    {
        if (expression is LambdaExpression)
            expression = ((LambdaExpression)expression).Body;

        if (expression is MemberExpression)
        {
            var memberExpression = (MemberExpression)expression;
            if (memberExpression.Expression.NodeType ==
                ExpressionType.MemberAccess)
            {
                return GetMemberName(memberExpression.Expression)
                       + "."
                       + memberExpression.Member.Name;
            }
            return memberExpression.Member.Name;
        }


        if (expression is UnaryExpression)
        {
            var unaryExpression = (UnaryExpression)expression;

            if (unaryExpression.NodeType != ExpressionType.Convert)
                throw new Exception(string.Format(
                    "Cannot interpret member from {0}",
                    expression));
            return GetMemberName(unaryExpression.Operand);
        }
        throw new Exception(string.Format(
            "Could not determine member from {0}",
            expression));
    }

es decir, quiero algo como:

if (expression is SomeExpressionThatReturnsAnInstance)
{
    return (name of type of instance);
}

Respuesta aceptada

He remontado esto a la construcción de la Expresión. Realmente no contiene ninguna información de instancia, y no hay forma de obtener el nombre del tipo.

static Expression<Func<object, object>> thisObject = x => x;

Por lo tanto, no hay forma de que un nombre de tipo se pueda derivar de una expresión que ni siquiera tenga un tipo (que no sea un objeto).

El método utilizado para generar una expresión que devuelve un nombre de propiedad:

LambdaExpression BuildExpression(Type rootType, string propertyName)
    {
        try
        {
            var properties = propertyName.Split('.');
            ParameterExpression arg = Expression.Parameter(rootType, "x");
            Expression expr = arg;
            foreach (string property in properties)
            {
                PropertyInfo propertyInfo = rootType.GetProperty(property);
                if (propertyInfo == null)
                    return null;
                expr = Expression.Property(expr, propertyInfo);
                rootType = propertyInfo.PropertyType;
            }
            return Expression.Lambda(expr, arg);
        }
        catch (System.Exception ex)
        {
            return null;
        }
    }

Respuesta popular

Puedo ser un malentendido, pero un x => x directo será un ParameterExpression . Solo agregue una prueba adicional en su prueba existente is MemberExpression :

if (expression is MemberExpression)
{
    // As-is
}
// New condition
if (expression is ParameterExpression)
{
    return expression.Type.Name;
}

Utilizando este código:

class Car { public string Color { get; set; }}

Expression<Func<Car, string>> expr1 = x => x.Color;
Expression<Func<Car, Car>> expr2 = x => x;

Console.WriteLine(GetMemberName(expr1));
> Color
Console.WriteLine(GetMemberName(expr2));
> Car


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow