using System; using System.Linq; using System.Linq.Expressions; namespace SKMC.Api.Common { public static class Predicator { 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); return Expression.Lambda>( func(left, right), parameter); } public static Expression> AggregateAnd(Expression>[] input) { return input.Aggregate((l, r) => l.And(r)); } 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) { if (node == _oldValue) return _newValue; return base.Visit(node); } } } }