如何读取表达式树中属性的值?

时间:2017-09-07 19:28:22

标签: c# expression-trees

我想阅读表达式树中某些属性的值,我可以进行一些计算。

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 个答案:

答案 0 :(得分:0)

您似乎正在使用数据库查询提供程序(LINQ2SQL,EF等)

在尝试使用表达式来解决问题之前,您需要确保查询提供程序能够理解表达式。在您的情况下,许多Math方法可以转换为T-SQL有效语句。此外,如果您正在使用实体框架,您可能希望利用System.Data.Objects.SqlClient.SqlFunctions类创建表达式并在SQL Server端执行逻辑以对抗本机T-SQL函数。

现在,在表达式树上要理解的一点是,无法从构造表达式中获取值,除非这是LambdaExpression,一旦编译后调用它,在你的情况下你可以获得bool值。

如果需要使用价格值,则需要创建更多表达对其他逻辑的调用的表达式,在您的示例中,调用Sqrt类的静态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;
}

正如您所看到的,所有逻辑都是表达式,并且提供程序可以使用整个表达式并将其转换为目标进程可以理解的语法。先前的表达式生成 p => Math.Sqrt((double)p.Price) > 4d