using System; using System.Collections.Generic; using System.Linq.Expressions; namespace InABox.Core { public static class PredicateExtensions { /// /// Begin an expression chain /// /// /// Default return value if the chanin is ended early /// A lambda expression stub public static Expression> Begin(bool value = false) { if (value) return parameter => true; //value cannot be used in place of true/false return parameter => false; } public static Expression> And(this Expression> left, Expression> right) { return CombineLambdas(left, right, ExpressionType.AndAlso); } public static Expression> Or(this Expression> left, Expression> right) { return CombineLambdas(left, right, ExpressionType.OrElse); } #region private private static Expression> CombineLambdas(this Expression> left, Expression> right, ExpressionType expressionType) { //Remove expressions created with Begin() if (IsExpressionBodyConstant(left)) return right; var p = left.Parameters[0]; var visitor = new SubstituteParameterVisitor(); visitor.Sub[right.Parameters[0]] = p; Expression body = Expression.MakeBinary(expressionType, left.Body, visitor.Visit(right.Body)); return Expression.Lambda>(body, p); } private static bool IsExpressionBodyConstant(Expression> left) { return left.Body.NodeType == ExpressionType.Constant; } internal class SubstituteParameterVisitor : ExpressionVisitor { public Dictionary Sub = new Dictionary(); protected override Expression VisitParameter(ParameterExpression node) { Expression newValue; if (Sub.TryGetValue(node, out newValue)) return newValue; return node; } } #endregion } }