Construir LambdaExpression para la propiedad anidada de cadena

.net c# expression-trees lambda linq

Pregunta

Estoy tratando de crear una expresión lambda para una propiedad anidada en tiempo de ejecución desde el nombre de la propiedad. Básicamente estoy tratando de crear la expresión lambda especificada por:

var expression = CreateExpression<Foo, object>(foo => foo.myBar.name);

private static Expression CreateExpression<TEntity, TReturn>(Expression<Func<TEntity, TReturn>> expression)
{
    return (expression as Expression);
}

Con las clases:

class Foo
{
    public Bar myBar { get; set; }
}
class Bar
{
    public string name { get; set; }
}

Sin embargo, todo lo que me dan es el tipo de Foo y la cadena "myBar.name"

Si fuera una propiedad normal, como solo necesitar el valor "myBar" , podría usar lo siguiente:

private static LambdaExpression GetPropertyAccessLambda(Type type, string propertyName)
{
    ParameterExpression odataItParameter = Expression.Parameter(type, "$it");
    MemberExpression propertyAccess = Expression.Property(odataItParameter, propertyName);
    return Expression.Lambda(propertyAccess, odataItParameter);
}

Sin embargo, este código no funciona para las propiedades anidadas y no estoy seguro de cómo crear LambdaExpression para hacer el trabajo de foo.myBar.name .

Creo que va a ser algo como esto:

GetExpression(Expression.Call(GetExpression(Foo, "myBar"), "name"))

Pero parece que no puedo encontrar la manera de hacer que todo funcione, o si hay una mejor manera de hacerlo en tiempo de ejecución.

Respuesta aceptada

Quieres decir:

static LambdaExpression CreateExpression(Type type, string propertyName) {
    var param = Expression.Parameter(type, "x");
    Expression body = param;
    foreach (var member in propertyName.Split('.')) {
        body = Expression.PropertyOrField(body, member);
    }
    return Expression.Lambda(body, param);
}

Por ejemplo:

class Foo {
    public Bar myBar { get; set; }
}
class Bar {
    public string name { get; set; }
}
static void Main() {
    var expression = CreateExpression(typeof(Foo), "myBar.name");
    // x => x.myBar.name
}

?



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