You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将多个Expression<Func<T1,T2,bool>>通过OrElse合并为Expression<Func<T2,bool>>

问题原因

你遇到的两个报错本质是表达式树的结构使用错误:

  • 不能直接将完整的Expression<Func<>>类型的Lambda表达式赋值给BinaryExpression,后者只对应Lambda内部的二元运算节点
  • OrElse只能拼接返回布尔值的表达式节点,不能直接拼接两个完整的Lambda表达式,两个Func类型之间不存在逻辑或运算定义
    另外你后续构造Lambda时参数数量不匹配,每个循环里创建的Lambda参数都是独立实例,直接拼接会出现参数引用不匹配的问题。
正确实现

步骤1:定义公共参数

所有拼接的条件复用同一组参数实例,避免参数不匹配:

// 定义两个公共参数,对应原表达式中的n和c
var paramN = Expression.Parameter(typeof(TNumbering), "n");
var paramC = Expression.Parameter(typeof(TConfiguration), "c");

步骤2:遍历拼接条件

BinaryExpression combinedBody = null;
foreach (var criteria in SelectionCriteria)
{
    // 构造获取配置字段的表达式:criteria.ConfigurationField(c)
    var configFieldExp = Expression.Invoke(
        Expression.Constant(criteria.ConfigurationField), 
        paramC
    );
    // 构造获取编号字段的表达式:criteria.NumberingField(n)
    var numberingFieldExp = Expression.Invoke(
        Expression.Constant(criteria.NumberingField), 
        paramN
    );
    // 构造不等于判断的二元表达式
    var notEqualExp = Expression.NotEqual(configFieldExp, numberingFieldExp);
    // 用OrElse拼接已有条件
    combinedBody = combinedBody == null ? notEqualExp : Expression.OrElse(combinedBody, notEqualExp);
}

步骤3:构造Lambda并调用

if (combinedBody == null)
{
    return Result.Failure("Expression not defined");
}
// 构造完整的过滤Lambda
var filterLambda = Expression.Lambda<Func<TNumbering, TConfiguration, bool>>(
    combinedBody, 
    paramN, 
    paramC
);
// 编译为委托供Linq to Objects使用,若用于EF等IQueryable场景不要编译,直接传入表达式
var filter = filterLambda.Compile();
// 执行过滤
numberingsToRemove = numberings.Where(n => configurations.All(c => filter(n, c))).ToList();
注意事项

如果你的逻辑是用于EF Core等ORM的IQueryable查询,不能使用Expression.Invoke和Compile方法,需要将两个属性的类型从Func<,>改为Expression<Func<,>>,再直接拼接表达式体即可。

内容的提问来源于stack exchange,提问作者Mkov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 10:15:04