NET 构建动态Lambda表达式 - 集合

ExpressionExtend

using System.Linq.Expressions;
using System.Reflection;

namespace CustCommon.Extends;

/// <summary>
/// 表达式扩展方法
/// </summary>
public static class ExpressionExtend
{
    /// <summary>
    /// 根据集合构建 or 表达式
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="paramList">查询条件集合</param>
    /// <param name="format">格式化条件</param>
    /// <param name="fieldName">db字段名</param>
    /// <returns></returns>
    public static Expression<Func<T, bool>> BuilderOr<T>(this List<string> paramList, string format, string fieldName)
    {
        //  如果参数集合为空 或 格式化字符串为空,直接返回null
        if (paramList.IsNullOrEmpty() || format.CustIsNullOrWhiteSpace()) return null;
        // 构建动态表达式: x.FieldName.Contains($",{code},") 任意一个满足即可
        Expression<Func<T, bool>> itemExpression = null;
        //  {x}
        ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
        //  {x.FieldName}
        MemberExpression itemKeysProperty = Expression.Property(parameter, fieldName);

        foreach (var code in paramList)
        {
            // 构建常量: $",{code},"
            ConstantExpression value = Expression.Constant(string.Format(format, code));

            // 构建方法调用: {Boolean Contains(System.String)}
            MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
            //  {x.FieldName.Contains(",25,")}
            MethodCallExpression containsCall = Expression.Call(itemKeysProperty, containsMethod, value);

            // 转换为Lambda表达式: {x => x.FieldName.Contains(",25,")}
            Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(containsCall, parameter);

            // 组合为OR条件
            if (itemExpression == null)
                //  {x => x.FieldName.Contains(",25,")}
                itemExpression = lambda;
            else
                //  {x => (x.FieldName.Contains(",25,") OrElse x.FieldName.Contains(",27,"))}
                itemExpression = itemExpression.Or(lambda);
        }
        //  最终表达式: {x => (x.FieldName.Contains(",25,") OrElse x.FieldName.Contains(",27,"))}
        return itemExpression;
    }

    /// <summary>
    /// 组合两个表达式为OR关系
    /// </summary>
    public static Expression<Func<T, bool>> Or<T>(
        this Expression<Func<T, bool>> left,
        Expression<Func<T, bool>> right)
    {
        var visitor = new ParameterRebinder(right.Parameters[0], left.Parameters[0]);
        var rightBody = visitor.Visit(right.Body);
        return Expression.Lambda<Func<T, bool>>(
            Expression.OrElse(left.Body, rightBody),
            left.Parameters);
    }

    private class ParameterRebinder : ExpressionVisitor
    {
        private readonly ParameterExpression _oldParam;
        private readonly ParameterExpression _newParam;

        public ParameterRebinder(ParameterExpression oldParam, ParameterExpression newParam)
        {
            _oldParam = oldParam;
            _newParam = newParam;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return node == _oldParam ? _newParam : base.VisitParameter(node);
        }
    }
}

调用

var itemLamda = list.BuilderOr<TableName>(",{0},", "FieldName");

 

posted @ 2025-08-05 11:06  Robot-Blog  阅读(8)  评论(0)    收藏  举报