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

如何在C#中构建复合表达式实现多字段不等判断的All查询逻辑

C# 表达式树拼接OrElse报错解决方案

错误原因

你无法直接对两个Expression<Func<>>类型的Lambda表达式执行OrElse运算:OrElse对应C#中的||运算符,仅支持对返回布尔值的表达式节点进行拼接,你传入的是完整的Lambda委托类型对象,自然没有对应的运算符实现,因此触发报错。

解决思路

统一所有条件使用的参数实例,提取每个判断逻辑的布尔表达式体进行拼接,最后再封装为完整的Lambda表达式即可。

修正后的代码示例

// 提前定义All遍历配置项时的统一参数
ParameterExpression configParam = Expression.Parameter(typeof(TConfiguration), "c");

// 把表达式构造逻辑放到Where的委托内,捕获当前遍历的numbering对象
numberingsToRemove = numberingsToRemove.Where(n => 
{
    Expression combinedOr = null;
    foreach (var criteria in SelectionCriteria)
    {
        // 提取配置项的字段访问表达式
        Expression configField = Expression.Invoke(criteria.ConfigurationField, configParam);
        // 提取当前numbering的字段访问表达式
        Expression numberingField = Expression.Invoke(criteria.NumberingField, Expression.Constant(n));
        // 构造不等判断的布尔表达式
        BinaryExpression notEqualExp = Expression.NotEqual(configField, numberingField);
        // 拼接Or逻辑
        combinedOr = combinedOr == null ? notEqualExp : Expression.OrElse(combinedOr, notEqualExp);
    }

    if (combinedOr == null) 
    {
        // 按你的业务逻辑处理空条件的情况
        return Result.Failure(string.Format(Errors.NumberingFieldSelectionNotDefined, $"{shipper}:{GetType().FullName}")).IsFailed;
    }

    // 拼接为针对配置项的Lambda表达式
    var checkLambda = Expression.Lambda<Func<TConfiguration, bool>>(combinedOr, configParam);
    // 编译后传入All方法
    return configsThatStay.All(checkLambda.Compile());
});

注意事项

  • 所有参与拼接的表达式必须使用同一个ParameterExpression实例作为参数,不能每次循环新建参数,否则会被表达式树识别为不同的变量,触发运行时错误。
  • 如果这段逻辑需要给EF Core等ORM框架执行(不能在表达式中调用Compile方法),可以自定义ExpressionVisitor替换Lambda参数,避免使用Invoke调用,适配ORM的表达式解析规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 20:24:04