2017-09-07 10 views
1

Je voudrais lire la valeur de certaines propriétés de l'arbre d'expression, je peux procéder à quelques calculs.Comment lire les valeurs d'une propriété dans l'arbre d'expression?

var products = db.Products 
    .Where(GetPredicate()) 
    .ToList(); 

private Expression<Func<Product, bool>> GetPredicate() 
{ 
    ParameterExpression pe = Expression.Parameter(typeof(Product), "p"); 
    Expression exp0 = Expression.Property(pe, "Price"); 

    //I'd like to know the value of the 'Price' 
    // so I can do some calculation, then check whether 
    //this particular product meet the criteria... 

    Expression body = Expression.Constant(Result); //result is a boolean 
    var expr = Expression.Lambda<Func<Product, bool>>(body, new ParameterExpression[] { pe }); 
     return expr; 

} 
+1

Avez-vous essayé d'utiliser Expression.Convert? – napi15

+0

Copie possible de [Lecture des propriétés d'un objet avec des arbres d'expression] (https://stackoverflow.com/questions/16436323/reading-properties-of-an-object-with-expression-trees) – johnnyRose

+1

Lorsque vous créez un arbre d'expressions dans 'GetPredicate' vous n'avez pas la valeur de' Price' (parce que vous n'avez pas d'objet 'Product'). Vous ne pouvez donc pas récupérer la valeur réelle avant de la transmettre à l'arbre d'expression compilé. Mais vous pouvez ajouter à l'arbre d'expression des types de comparaisons et de contraintes comme vous le souhaitez. Quelque chose ressemble à ceci: 'Expression.Add (exp0, Expression.Constant (156));' alors vous pouvez vérifier la valeur retournée et etc. Mais vous ne connaissez pas encore la valeur, vous savez seulement que votre valeur d'entrée sera comparée Et ai-je raté quelque chose ou n'ai pas compris votre question? –

Répondre

0

Vous semblez utiliser un fournisseur de requête de base de données (LINQ2SQL, EF, etc.)

Avant d'essayer d'utiliser des expressions pour résoudre votre problème, vous devez vous assurer que l'expression est entendu par la requête fournisseur. Dans votre cas, la plupart des méthodes Math peuvent être converties en instructions valides T-SQL. En outre, si vous utilisez Entity Framework, vous pouvez utiliser la classe System.Data.Objects.SqlClient.SqlFunctions pour créer une expression et exécuter votre logique du côté de SQL Server contre les fonctions T-SQL natives.

Maintenant, quelque chose à comprendre sur les arbres d'expression, est que les valeurs ne peuvent pas être obtenues à partir d'expressions construire à moins que cela est un LambdaExpression, une fois compilé vous invoquez, dans votre cas, vous pouvez obtenir la valeur bool.

Si vous devez travailler avec la valeur de prix, vous devez créer plus d'expressions représentant l'appel à l'autre logique, dans votre exemple les expressions appelant la méthode Sqrt statique de la classe Math.

private Expression<Func<Product, bool>> GetPredicate() 
{ 
    var pe = Expression.Parameter(typeof(Product), "p"); 
    var price = Expression.Property(pe, "Price"); 
    var priceDouble = Expression.Convert(price, typeof(double)); 
    var sqrtMethod = typeof(Math).GetMethod("Sqrt"); 
    var sqrtCall = Expression.Call(sqrtMethod, priceDouble); 
    var constant = Expression.Constant(4d); 
    var gtThan = Expression.GreaterThan(sqrtCall, constant); 

    var lambda = Expression.Lambda<Func<Product, bool>>(gtThan, pe); 
    return lambda; 
} 

Comme vous pouvez le voir toute la logique est une expression et le fournisseur peut consommer toute l'expression et le convertir à la syntaxe qui peut être comprise par le processus cible. L'expression précédente génère p => Math.Sqrt((double)p.Price) > 4d