using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; namespace HL_FristAidPlatform_Help { /// /// 表达式构建器 /// public static class PredicateBuilder { #region Expression Joiner /// /// 创建一个值恒为 true 的表达式。 /// /// 表达式方法类型 /// 一个值恒为 true 的表达式。 public static Expression> True() { return p => true; } /// /// 创建一个值恒为 false 的表达式。 /// /// 表达式方法类型 /// 一个值恒为 false 的表达式。 public static Expression> False() { return f => false; } /// /// 使用 Expression.OrElse 的方式拼接两个 System.Linq.Expression。 /// /// 表达式方法类型 /// 左边的 System.Linq.Expression 。 /// 右边的 System.Linq.Expression。 /// 拼接完成的 System.Linq.Expression。 public static Expression Or(this Expression left, Expression right) { return MakeBinary(left, right, Expression.OrElse); } /// /// 使用 Expression.AndAlso 的方式拼接两个 System.Linq.Expression。 /// /// 表达式方法类型 /// 左边的 System.Linq.Expression 。 /// 右边的 System.Linq.Expression。 /// 拼接完成的 System.Linq.Expression。 public static Expression And(this Expression left, Expression right) { return MakeBinary(left, right, Expression.AndAlso); } /// /// 使用自定义的方式拼接两个 System.Linq.Expression。 /// /// 表达式方法类型 /// 左边的 System.Linq.Expression 。 /// 右边的 System.Linq.Expression。 /// 拼接完成的 System.Linq.Expression。 public static Expression MakeBinary(this Expression left, Expression right, Func func) { return MakeBinary((LambdaExpression)left, right, func) as Expression; } /// /// 拼接两个 ,两个 的参数必须完全相同。 /// /// 表达式中的元素类型 /// 左边的 /// 右边的 /// 表达式拼接的具体逻辑 /// 拼接完成的 public static LambdaExpression MakeBinary(this LambdaExpression left, LambdaExpression right, Func func) { var data = Combinate(right.Parameters, left.Parameters).ToArray(); right = ParameterReplace.Replace(right, data) as LambdaExpression; return Expression.Lambda(func(left.Body, right.Body), left.Parameters.ToArray()); } #endregion #region Private Methods private static IEnumerable> Combinate(IEnumerable left, IEnumerable right) { var a = left.GetEnumerator(); var b = right.GetEnumerator(); while (a.MoveNext() && b.MoveNext()) yield return new KeyValuePair(a.Current, b.Current); } #endregion public static IQueryable Between (this IQueryable source, Expression> keySelector, TKey low, TKey high) where TKey : IComparable { Expression key = Expression.Invoke(keySelector, keySelector.Parameters.ToArray()); Expression lowerBound = Expression.GreaterThanOrEqual (key, Expression.Constant(low)); Expression upperBound = Expression.LessThanOrEqual (key, Expression.Constant(high)); Expression and = Expression.AndAlso(lowerBound, upperBound); Expression> lambda = Expression.Lambda>(and, keySelector.Parameters); return source.Where(lambda); } } #region class: ParameterReplace internal sealed class ParameterReplace : ExpressionVisitor { public static Expression Replace(Expression e, IEnumerable> paramList) { var item = new ParameterReplace(paramList); return item.Visit(e); } private Dictionary parameters = null; public ParameterReplace(IEnumerable> paramList) { parameters = paramList.ToDictionary(p => p.Key, p => p.Value, new ParameterEquality()); } protected override Expression VisitParameter(ParameterExpression p) { ParameterExpression result; if (parameters.TryGetValue(p, out result)) return result; else return base.VisitParameter(p); } #region class: ParameterEquality private class ParameterEquality : IEqualityComparer { public bool Equals(ParameterExpression x, ParameterExpression y) { if (x == null || y == null) return false; return x.Type == y.Type; } public int GetHashCode(ParameterExpression obj) { if (obj == null) return 0; return obj.Type.GetHashCode(); } } #endregion } #endregion }