using System; using System.Linq.Expressions; namespace detect.gui.Commons; public static class PredicateBuilder { public static Expression> GetTrue() { return f => true; } public static Expression> GetFalse() { return f => false; } public static Expression> And(this Expression> first, Expression> second) { return first.AndAlso(second, Expression.AndAlso); } public static Expression> Or(this Expression> first, Expression> second) { return first.AndAlso(second, Expression.OrElse); } private static Expression> AndAlso(this Expression> expr1, Expression> expr2, Func func) { var parameter = Expression.Parameter(typeof(T)); var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter); var left = leftVisitor.Visit(expr1.Body); var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter); var right = rightVisitor.Visit(expr2.Body); if (left == null || right == null) return Expression.Lambda>(() => true); return Expression.Lambda>(func(left, right), parameter); } private class ReplaceExpressionVisitor : ExpressionVisitor { private readonly Expression? _oldValue; private readonly Expression? _newValue; public ReplaceExpressionVisitor(Expression? oldValue, Expression? newValue) { _oldValue = oldValue; _newValue = newValue; } public override Expression? Visit(Expression? node) { return node == _oldValue ? _newValue : base.Visit(node); } } }