.net 合并2个列表,列表〈表达式< Func>>与它们之间的OR和项目之间的OR/AND [重复]

yxyvkwin  于 2023-03-31  发布在  .NET
关注(0)|答案(1)|浏览(98)

此问题在此处已有答案

Combining two expressions (Expression<Func<T, bool>>)(10个答案)
昨天关门了。
社区正在审查是否从昨天开始重新讨论这个问题。
我有两份名单

List<Expression<Func<MyClass, bool>>> andConditions = new List<Expression<Func<MyClass, bool>>>();

List<Expression<Func<MyClass, bool>>> orConditions = new List<Expression<Func<MyClass, bool>>>();

第一个,我想在每个项目之间使用AND,第二个在每个项目之间使用OR。最后,我想用OR合并这两个列表。
结果示例:

exprList1 AND exprList1 OR exprList2 OR exprList2 OR exprList2

你能告诉我这件事吗?

abithluo

abithluo1#

您可以使用PredicateBuilderLINQKit nuget包。
在所有促使你手动构建表达式树的因素中,动态 predicate 的需求在典型的业务应用程序中是最常见的。幸运的是,可以编写一组简单的、可重用的扩展方法,从根本上简化这项任务。这就是我们的PredicateBuilder类的作用。
首先安装nuget包:

Install-Package LinqKit

之后你可以使用PredicateBuilder来合并表达式。长版本:

// AND
var combinedAnd = PredicateBuilder.New<MyClass>(true);
foreach (var andCondition in andConditions)
{
    combinedAnd = combinedAnd.And(andCondition);
}

// OR
var combinedOr = PredicateBuilder.New<MyClass>(false);
foreach (var orCondition in orConditions)
{
    combinedOr = combinedOr.Or(orCondition);
}

var finalExpression = combinedAnd.Or(combinedOr);

基于LINQ的短版本:

var combinedAnd = andConditions
    .Aggregate(
        PredicateBuilder.New<MyClass>(true), 
        (current, andCondition) => current.And(andCondition));
var combinedOr = orConditions
    .Aggregate(
        PredicateBuilder.New<MyClass>(false), 
        (current, orCondition) => current.Or(orCondition));
var finalExpression = combinedAnd.Or(combinedOr);

PredicateBuilder.New<MyClass>(true)返回一个初始 predicate ,该 predicate 返回true。将 predicate 与AND操作组合是合适的行为,因为它将创建true && predicate_1 && ... && predicate_n结果。PredicateBuilder.New<MyClass>(false)适合于OR操作。
如果你不能使用外部库,你可以自己实现合并表达式的方法:

public static class ExpressionExtensions
{
    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
    {
        var parameter = Expression.Parameter(typeof(T), "x");
        var body = Expression.And(
            Expression.Invoke(expr1, parameter),
            Expression.Invoke(expr2, parameter)
        );
        return Expression.Lambda<Func<T, bool>>(body, parameter);
    }

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
    {
        var parameter = Expression.Parameter(typeof(T), "x");
        var body = Expression.Or(
            Expression.Invoke(expr1, parameter),
            Expression.Invoke(expr2, parameter)
        );
        return Expression.Lambda<Func<T, bool>>(body, parameter);
    }
}

并在代码中使用它:

var combinedAnd = andConditions.Aggregate((expr1, expr2) => expr1.And(expr2));
var combinedOr = orConditions.Aggregate((expr1, expr2) => expr1.Or(expr2));
var finalExpression = combinedAnd.Or(combinedOr);

相关问题