C#:将InvocationExpression转为BinaryExpression以获取Lambda左右操作数
解决Lambda表达式Body为InvocationExpression时获取二元操作数的问题
问题根源
你遇到的Body是InvocationExpression而非BinaryExpression,通常有两种原因:
- 你把编译后的
Func<T,bool>反向转换为表达式树,这会破坏原始的二元表达式结构,生成的是对委托调用的表达式。 - 你的Lambda表达式本质是调用了一个返回bool的方法(比如自定义比较逻辑),而非直接的二元运算符表达式。
可行解决方案
1. 从InvocationExpression中提取内部BinaryExpression
如果是因为委托包装导致的InvocationExpression,可以逐层拆解,检查内部是否包含Lambda表达式,进而获取原始的二元表达式:
// 假设expr是你拿到的Expression<Func<T, bool>> if (expr.Body is InvocationExpression invocation) { if (invocation.Expression is LambdaExpression innerLambda && innerLambda.Body is BinaryExpression binaryExpr) { // 获取左右操作数 var left = binaryExpr.Left; var right = binaryExpr.Right; // 编译操作数表达式,计算具体实例的值 var leftEvaluator = Expression.Lambda<Func<T, object>>( Expression.Convert(left, typeof(object)), expr.Parameters[0]).Compile(); var rightEvaluator = Expression.Lambda<Func<T, object>>( Expression.Convert(right, typeof(object)), expr.Parameters[0]).Compile(); // 对目标实例计算值 T targetInstance = /* 你的实例 */; var leftValue = leftEvaluator(targetInstance); var rightValue = rightEvaluator(targetInstance); } }
2. 全程使用表达式树类型,避免提前编译
如果你的代码是先把Lambda编译成Func<T,bool>再尝试转回表达式树,这完全是多此一举。直接使用Expression<Func<T,bool>>类型,就能保留原始的二元表达式结构:
// 直接定义表达式树,不要编译为Func Expression<Func<YourEntity, bool>> filterExpr = x => x.Foo < x.Bar; if (filterExpr.Body is BinaryExpression binaryExpr) { var leftOperand = binaryExpr.Left; var rightOperand = binaryExpr.Right; // 计算操作数值的逻辑同上 }
3. 处理方法调用型的InvocationExpression
如果你的Lambda是调用了一个接收两个参数的bool返回值方法(比如x => Compare(x.Foo, x.Bar)),可以直接从InvocationExpression的Arguments集合中提取操作数:
if (expr.Body is InvocationExpression invocation) { if (invocation.Arguments.Count == 2) { var leftOperand = invocation.Arguments[0]; var rightOperand = invocation.Arguments[1]; // 编译计算值的逻辑同上 } }
内容的提问来源于stack exchange,提问作者doozly
相关产品推荐
相关产品推荐

