Accede al valor de una expresión miembro

c# expression-trees lambda linq

Pregunta

Si tengo un producto.

var p = new Product { Price = 30 };

y tengo la siguiente consulta linq.

var q = repo.Products().Where(x=>x.Price == p.Price).ToList()

En un proveedor de IQueryable, obtengo una Expresión miembro para el precio p.que contiene una Expresión constante, sin embargo, parece que no puedo recuperar el valor "30".

Actualización He intentado esto, pero no parece funcionar.

var memberExpression = (MemberExpression)GetRootConstantExpression(m);
var fi = (PropertyInfo)memberExpression.Member;
var val = fi.GetValue(((ConstantExpression)memberExpression.Expression).Value, null);

Aclamaciones.

Respuesta aceptada

Puede compilar e invocar una expresión lambda cuyo cuerpo es el acceso de miembros:

private object GetValue(MemberExpression member)
{
    var objectMember = Expression.Convert(member, typeof(object));

    var getterLambda = Expression.Lambda<Func<object>>(objectMember);

    var getter = getterLambda.Compile();

    return getter();
}

La evaluación local es una técnica común cuando se analizan los árboles de expresión. LINQ to SQL hace esto exactamente en unos cuantos lugares.


Respuesta experta

La expresión constante va a apuntar a una clase de captura generada por el compilador. No he incluido los puntos de decisión, etc., pero aquí hay cómo obtener 30 de eso:

var p = new Product { Price = 30 };
Expression<Func<Product, bool>> predicate = x => x.Price == p.Price;
BinaryExpression eq = (BinaryExpression)predicate.Body;
MemberExpression productToPrice = (MemberExpression)eq.Right;
MemberExpression captureToProduct = (MemberExpression)productToPrice.Expression;
ConstantExpression captureConst = (ConstantExpression)captureToProduct.Expression;
object product = ((FieldInfo)captureToProduct.Member).GetValue(captureConst.Value);
object price = ((PropertyInfo)productToPrice.Member).GetValue(product, null);

price es ahora de 30 . Tenga en cuenta que asumo que Price es una propiedad, pero en realidad escribiría un método GetValue que maneja la propiedad / campo.



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