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
}
}