using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Linq; using System.Text; #region << 版 本 注 释 >> /*-------------------------------------------------------------------- * 版权所有 (c) 2024 WenJY 保留所有权利。 * CLR版本:4.0.30319.42000 * 机器名称:LAPTOP-E0N2L34V * 命名空间:SlnMesnac.Common * 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82 * * 创建者:WenJY * 电子邮箱:wenjy@mesnac.com * 创建时间:2024-03-27 21:58:35 * 版本:V1.0.0 * 描述: * *-------------------------------------------------------------------- * 修改人: * 时间: * 修改说明: * * 版本:V1.0.0 *--------------------------------------------------------------------*/ #endregion << 版 本 注 释 >> namespace SlnMesnac.Common { /// <summary> /// 谓词表达式构建器 /// </summary> public static class ExpressionExtensions { /// <summary> /// 创建一个值恒为 <c>true</c> 的表达式。 /// </summary> /// <typeparam name="T">表达式方法类型</typeparam> /// <returns>一个值恒为 <c>true</c> 的表达式。</returns> public static Expression<Func<T, bool>> True<T>() { return p => true; } /// <summary> /// 创建一个值恒为 <c>false</c> 的表达式。 /// </summary> /// <typeparam name="T">表达式方法类型</typeparam> /// <returns>一个值恒为 <c>false</c> 的表达式。</returns> public static Expression<Func<T, bool>> False<T>() { return f => false; } /// <summary> /// 使用 Expression.OrElse 的方式拼接两个 System.Linq.Expression。 /// </summary> /// <typeparam name="T">表达式方法类型</typeparam> /// <param name="left">左边的 System.Linq.Expression 。</param> /// <param name="right">右边的 System.Linq.Expression。</param> /// <returns>拼接完成的 System.Linq.Expression。</returns> public static Expression<T> Or<T>(this Expression<T> left, Expression<T> right) { return MakeBinary(left, right, Expression.OrElse); } /// <summary> /// 使用 Expression.AndAlso 的方式拼接两个 System.Linq.Expression。 /// </summary> /// <typeparam name="T">表达式方法类型</typeparam> /// <param name="left">左边的 System.Linq.Expression 。</param> /// <param name="right">右边的 System.Linq.Expression。</param> /// <returns>拼接完成的 System.Linq.Expression。</returns> public static Expression<T> And<T>(this Expression<T> left, Expression<T> right) { return MakeBinary(left, right, Expression.AndAlso); } /// <summary> /// 使用自定义的方式拼接两个 System.Linq.Expression。 /// </summary> /// <typeparam name="T">表达式方法类型</typeparam> /// <param name="left">左边的 System.Linq.Expression 。</param> /// <param name="right">右边的 System.Linq.Expression。</param> /// <param name="func"> </param> /// <returns>拼接完成的 System.Linq.Expression。</returns> private static Expression<T> MakeBinary<T>(this Expression<T> left, Expression<T> right, Func<Expression, Expression, Expression> func) { return MakeBinary((LambdaExpression)left, right, func) as Expression<T>; } /// <summary> /// 拼接两个 <paramref> /// <name>System.Linq.Expression</name> /// </paramref> ,两个 <paramref> /// <name>System.Linq.Expression</name> /// </paramref> 的参数必须完全相同。 /// </summary> /// <param name="left">左边的 <paramref> /// <name>System.Linq.Expression</name> /// </paramref> </param> /// <param name="right">右边的 <paramref> /// <name>System.Linq.Expression</name> /// </paramref> </param> /// <param name="func">表达式拼接的具体逻辑</param> /// <returns>拼接完成的 <paramref> /// <name>System.Linq.Expression</name> /// </paramref> </returns> private static LambdaExpression MakeBinary(this LambdaExpression left, LambdaExpression right, Func<Expression, Expression, Expression> 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()); } /// <summary> /// 合并参数 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="left"></param> /// <param name="right"></param> /// <returns></returns> private static IEnumerable<KeyValuePair<T, T>> Combinate<T>(IEnumerable<T> left, IEnumerable<T> right) { var a = left.GetEnumerator(); var b = right.GetEnumerator(); while (a.MoveNext() && b.MoveNext()) yield return new KeyValuePair<T, T>(a.Current, b.Current); } } internal sealed class ParameterReplace : ExpressionVisitor { public static Expression Replace(Expression e, IEnumerable<KeyValuePair<ParameterExpression, ParameterExpression>> paramList) { var item = new ParameterReplace(paramList); return item.Visit(e); } private readonly Dictionary<ParameterExpression, ParameterExpression> _parameters; public ParameterReplace(IEnumerable<KeyValuePair<ParameterExpression, ParameterExpression>> 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; return base.VisitParameter(p); } #region class: ParameterEquality private class ParameterEquality : IEqualityComparer<ParameterExpression> { 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 } }