| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 | using System;using System.Collections.Generic;using System.Linq.Expressions;namespace InABox.Core{    public static class PredicateExtensions    {        /// <summary>        ///     Begin an expression chain        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="value">Default return value if the chanin is ended early</param>        /// <returns>A lambda expression stub</returns>        public static Expression<Func<T, bool>> Begin<T>(bool value = false)        {            if (value)                return parameter => true; //value cannot be used in place of true/false            return parameter => false;        }        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> left,            Expression<Func<T, bool>> right)        {            return CombineLambdas(left, right, ExpressionType.AndAlso);        }        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)        {            return CombineLambdas(left, right, ExpressionType.OrElse);        }        #region private        private static Expression<Func<T, R>> CombineLambdas<T, R>(this Expression<Func<T, R>> left,            Expression<Func<T, R>> right, ExpressionType expressionType)        {            //Remove expressions created with Begin<T>()            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<Func<T, R>>(body, p);        }        private static bool IsExpressionBodyConstant<T, R>(Expression<Func<T, R>> left)        {            return left.Body.NodeType == ExpressionType.Constant;        }        internal class SubstituteParameterVisitor : ExpressionVisitor        {            public Dictionary<Expression, Expression> Sub = new Dictionary<Expression, Expression>();            protected override Expression VisitParameter(ParameterExpression node)            {                Expression newValue;                if (Sub.TryGetValue(node, out newValue)) return newValue;                return node;            }        }        #endregion    }}
 |