从BinaryExpression到Expression <Func >

假设我有类似的东西

Expression<Func> left = x => x.SomeDateProperty; Expression<Func> right = x => dateTimeConstant; var binaryExpression = Expression.GreaterThan(left, right); Expression<Func> predicate = x => x.SomeDateProperty> dateTimeConstant; 

1)如何使用binaryExpression替换最后一行赋值的binaryExpressionvar predicate = x => binaryExpression; 不起作用。

2) right总是一个常数,不一定是DateTime.Now。 它可能是一些更简单的Expression吗? 例如,它不依赖于SomeType,它只是一个常量。

3)如果我将GreaterThan作为string ,有没有办法从这个字符串到Expression具有相同名称的方法? 通常,如果比较方法的名称是以stringforms给出的,那么如何从字符串转到实际调用Expression类中具有相同名称的方法?

如果重要的话,它必须与LINQ to Entities一起使用。

1和2:您需要手动构建表达式树来执行此操作,编译器无法提供帮助,因为它只构造完整表示函数的现成表达式。 当你想要逐个构建函数时,这没用。

这是构建所需表达式的一种直接方式:

 var argument = Expression.Parameter(typeof(SomeType)); var left = Expression.Property(argument, "SomeDateProperty"); var right = Expression.Constant(DateTime.Now); var predicate = Expression.Lambda>( Expression.GreaterThan(left, right), new[] { argument } ); 

您可以将其用于试驾

 var param = new SomeType { SomeDateProperty = DateTime.Now.Add(TimeSpan.FromHours(-1)) }; Console.WriteLine(predicate.Compile()(param)); // "False" 

3:由于二进制谓词的可能选择数量很可能非常小,您可以使用字典执行此操作:

 var wordToExpression = new Dictionary> { { "GreaterThan", Expression.GreaterThan }, // etc }; 

然后,不是在第一个片段中对Expression.GreaterThan进行硬编码,而是执行类似wordToExpression["GreaterThan"](left, right)

当然,这也可以通过reflection的标准方式完成。

使用GreaterThan ,需要指定表达式主体 ,而不是lambda本身。 不幸的是,有一个复杂因素:两个表达式中的x 不一样

在这种特殊情况下,你可以侥幸逃脱,因为第二个表达式不使用x

所以; 您的“1”和“2”应该通过以下方式回答:

 var binaryExpression = Expression.GreaterThan(left.Body, right.Body); var lambda = Expression.Lambda>(binaryExpression, left.Parameters); 

但是,要在一般情况下处理此问题,您必须重写表达式,以修复参数:

 var binaryExpression = Expression.GreaterThan(left.Body, new SwapVisitor(right.Parameters[0], left.Parameters[0]).Visit(right.Body)); var lambda = Expression.Lambda>(binaryExpression, left.Parameters); 

有:

 public class SwapVisitor : ExpressionVisitor { private readonly Expression from, to; public SwapVisitor(Expression from, Expression to) { this.from = from; this.to = to; } public override Expression Visit(Expression node) { return node == from ? to : base.Visit(node); } } 

为你的“3”; 没有内置的东西; 但你可以使用reflection:

 string method = "GreaterThan"; var op = typeof(Expression).GetMethod(method, BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(Expression), typeof(Expression) }, null); var rightBody = new SwapVisitor(right.Parameters[0], left.Parameters[0]).Visit(right.Body); var exp = (Expression)op.Invoke(null, new object[] { left.Body, rightBody }); var lambda = Expression.Lambda>(exp, left.Parameters);