72 votes

Accéder à la valeur d'une expression de membre

Si j'ai un produit.

 var p = new Product { Price = 30 };
 

et j'ai la requête linq suivante.

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

Dans un fournisseur IQueryable, je récupère une expression MemberExpression pour le p.Price qui contient une expression constante, mais il me semble impossible d'obtenir la valeur "30".

Mise à jour J'ai essayé ceci mais cela ne semble pas fonctionner.

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

À votre santé.

129voto

Bryan Watts Points 22810

Vous pouvez compiler et appeler une expression lambda dont le corps est l'accès membre:

 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();
}
 

L'évaluation locale est une technique courante lors de l'analyse des arbres d'expression. LINQ to SQL fait exactement cela dans plusieurs endroits.

40voto

Glennular Points 8324
 MemberExpression right = (MemberExpression)((BinaryExpression)p.Body).Right;
 Expression.Lambda(right).Compile().DynamicInvoke();

28voto

Marc Gravell Points 482669

L'expression constante va pointer sur une classe de capture générée par le compilateur. Je n'ai pas inclus les points de décision, etc., mais voici comment en obtenir 30:

 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 est maintenant 30 . Notez que je suppose que Price est une propriété, mais en réalité, vous écririez une méthode GetValue qui gère la propriété / le champ.

1voto

Kirk Broadhurst Points 13093

q est du type List<Product> . La liste n'a pas de propriété Price, mais uniquement les produits individuels.

Le premier ou le dernier produit aura un prix.

 q.First().Price
q.Last().Price
 

Si vous savez qu’il n’y en a qu’un dans la collection, vous pouvez aussi l’aplatir avec Single.

 q.Single().Price
 

1voto

Henk Holterman Points 153608

Pouvez-vous utiliser les éléments suivants:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X