using System.Collections;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;
using AutoMapper.Internal;

namespace Dpz.Core.Entity.Base.ExpressTreeQuery;

/// <summary>
/// 条件过滤表达式树生成器
/// 用于根据请求参数动态生成 LINQ 表达式树,实现灵活的查询条件构建
/// </summary>
public static class GenerateConditionFilter
{
    /// <summary>
    /// 默认属性值的标识符
    /// 当 QueryFilterAttribute 的 PropertyValue 等于此值时,将使用属性自身的值作为比较值
    /// </summary>
    internal const string DefaultPropertyValue = "10001";

    /// <summary>
    /// 属性缓存字典
    /// 用于缓存类型的属性信息,提高反射性能
    /// Key: 类型
    /// Value: 该类型的所有属性信息数组
    /// </summary>
    private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PropertyCache = new();

    /// <summary>
    /// 获取类型的所有属性,并缓存结果
    /// </summary>
    /// <param name="type">要获取属性的类型</param>
    /// <returns>属性信息数组</returns>
    private static PropertyInfo[] GetProperties(Type type)
    {
        return PropertyCache.GetOrAdd(type, t => t.GetProperties());
    }

    /// <summary>
    /// 为单个实体类型生成条件表达式树
    /// </summary>
    /// <typeparam name="T">实体类型</typeparam>
    /// <typeparam name="TRequest">请求参数类型</typeparam>
    /// <param name="request">请求参数实例</param>
    /// <returns>条件表达式树,形如:x => x.Property1 == value1 && x.Property2 > value2</returns>
    public static Expression<Func<T, bool>> GenerateConditionExpressionTree<T, TRequest>(
        TRequest request
    )
    {
        return GenerateConditionExpressionTree<Func<T, bool>, TRequest>(request, typeof(T));
    }

    /// <summary>
    /// 为两个实体类型生成条件表达式树
    /// </summary>
    /// <typeparam name="T">第一个实体类型</typeparam>
    /// <typeparam name="T2">第二个实体类型</typeparam>
    /// <typeparam name="TRequest">请求参数类型</typeparam>
    /// <param name="request">请求参数实例</param>
    /// <returns>条件表达式树,形如:(x, y) => x.Property1 == value1 && y.Property2 > value2</returns>
    public static Expression<Func<T, T2, bool>> GenerateConditionExpressionTree<T, T2, TRequest>(
        TRequest request
    )
    {
        return GenerateConditionExpressionTree<Func<T, T2, bool>, TRequest>(
            request,
            typeof(T),
            typeof(T2)
        );
    }

    /// <summary>
    /// 为三个实体类型生成条件表达式树
    /// </summary>
    /// <typeparam name="T">第一个实体类型</typeparam>
    /// <typeparam name="T2">第二个实体类型</typeparam>
    /// <typeparam name="T3">第三个实体类型</typeparam>
    /// <typeparam name="TRequest">请求参数类型</typeparam>
    /// <param name="request">请求参数实例</param>
    /// <returns>条件表达式树,形如:(x, y, z) => x.Property1 == value1 && y.Property2 > value2 && z.Property3 != value3</returns>
    public static Expression<Func<T, T2, T3, bool>> GenerateConditionExpressionTree<
        T,
        T2,
        T3,
        TRequest
    >(TRequest request)
    {
        return GenerateConditionExpressionTree<Func<T, T2, T3, bool>, TRequest>(
            request,
            typeof(T),
            typeof(T2),
            typeof(T3)
        );
    }

    /// <summary>
    /// 为四个实体类型生成条件表达式树
    /// </summary>
    /// <typeparam name="T">第一个实体类型</typeparam>
    /// <typeparam name="T2">第二个实体类型</typeparam>
    /// <typeparam name="T3">第三个实体类型</typeparam>
    /// <typeparam name="T4">第四个实体类型</typeparam>
    /// <typeparam name="TRequest">请求参数类型</typeparam>
    /// <param name="request">请求参数实例</param>
    /// <returns>
    /// 条件表达式树,形如:
    /// <![CDATA[(x, y, z, w) => x.Property1 == value1 && y.Property2 > value2 && z.Property3 != value3 && w.Property4 <= value4]]>
    /// </returns>
    public static Expression<Func<T, T2, T3, T4, bool>> GenerateConditionExpressionTree<
        T,
        T2,
        T3,
        T4,
        TRequest
    >(TRequest request)
    {
        return GenerateConditionExpressionTree<Func<T, T2, T3, T4, bool>, TRequest>(
            request,
            typeof(T),
            typeof(T2),
            typeof(T3),
            typeof(T4)
        );
    }

    /// <summary>
    /// 为五个实体类型生成条件表达式树
    /// </summary>
    /// <typeparam name="T">第一个实体类型</typeparam>
    /// <typeparam name="T2">第二个实体类型</typeparam>
    /// <typeparam name="T3">第三个实体类型</typeparam>
    /// <typeparam name="T4">第四个实体类型</typeparam>
    /// <typeparam name="T5">第五个实体类型</typeparam>
    /// <typeparam name="TRequest">请求参数类型</typeparam>
    /// <param name="request">请求参数实例</param>
    /// <returns>
    /// 条件表达式树,形如:
    /// <![CDATA[(x, y, z, w, v) => x.Property1 == value1 && y.Property2 > value2 && z.Property3 != value3 && w.Property4 <= value4 && v.Property5 >= value5]]>
    /// </returns>
    public static Expression<Func<T, T2, T3, T4, T5, bool>> GenerateConditionExpressionTree<
        T,
        T2,
        T3,
        T4,
        T5,
        TRequest
    >(TRequest request)
    {
        return GenerateConditionExpressionTree<Func<T, T2, T3, T4, T5, bool>, TRequest>(
            request,
            typeof(T),
            typeof(T2),
            typeof(T3),
            typeof(T4),
            typeof(T5)
        );
    }

    /// <summary>
    /// 核心方法:根据请求参数和实体类型生成条件表达式树
    /// </summary>
    /// <typeparam name="TFunc">委托类型</typeparam>
    /// <typeparam name="TRequest">请求参数类型</typeparam>
    /// <param name="request">请求参数实例</param>
    /// <param name="additionalTypes">实体类型数组</param>
    /// <returns>条件表达式树</returns>
    /// <remarks>
    /// 处理流程:
    /// 1. 为每个实体类型创建参数表达式
    /// 2. 获取请求参数类型的所有属性,并处理带有 QueryFilterAttribute 特性的属性
    /// 3. 根据属性的 QueryFilterAttribute 特性生成对应的条件表达式
    /// 4. 将所有条件表达式用 AND 连接起来
    /// 5. 如果没有生成任何条件表达式,则返回始终为 true 的表达式
    /// </remarks>
    private static Expression<TFunc> GenerateConditionExpressionTree<TFunc, TRequest>(
        TRequest request,
        params Type[] additionalTypes
    )
        where TFunc : Delegate
    {
        // 为每个实体类型创建参数表达式
        var parameters = additionalTypes
            .Select((x, index) => Expression.Parameter(x, $"__q{(index == 0 ? "" : index)}"))
            .ToList();

        // 获取请求参数类型的所有属性,并处理带有QueryFilterAttribute特性的属性
        var queryFieldsExpression = GetProperties(typeof(TRequest))
            .SelectMany(x =>
            {
                var attributes = x.GetCustomAttributes<QueryFilterAttribute>();
                var value = x.GetValue(request);
                return HandleField(
                    parameters,
                    GetPropertyInfoByAttr,
                    GetValueByAttr,
                    attributes,
                    value
                );

                // 根据特性获取对应的属性信息
                PropertyInfo? GetPropertyInfoByAttr(QueryFilterAttribute attr) =>
                    (
                        additionalTypes.Length == 1 ? additionalTypes[0] : attr.EntityType
                    )?.GetProperty(attr.PropertyName ?? x.Name);

                // 获取用于比较的值
                object? GetValueByAttr(QueryFilterAttribute attr) =>
                    attr.PropertyValue?.Equals(DefaultPropertyValue) == true
                        ? value
                        : attr.PropertyValue;
            })
            .ToList();

        // 如果没有生成任何条件表达式,则返回始终为true的表达式
        if (queryFieldsExpression.Count == 0)
        {
            return Expression.Lambda<TFunc>(Expression.Constant(true), parameters.ToArray());
        }

        // 将所有条件表达式用AND连接起来
        var finalExpression = queryFieldsExpression.Aggregate(Expression.AndAlso);
        return Expression.Lambda<TFunc>(finalExpression, parameters.ToArray());
    }

    /// <summary>
    /// 处理单个字段的过滤条件,生成对应的表达式
    /// </summary>
    /// <param name="parameters">参数表达式列表</param>
    /// <param name="propertyFunc">获取属性信息的函数</param>
    /// <param name="valueFunc">获取比较值的函数</param>
    /// <param name="attributes">查询过滤特性集合</param>
    /// <param name="selfValue">属性自身的值</param>
    /// <returns>生成的表达式集合</returns>
    /// <remarks>
    /// 处理流程:
    /// 1. 遍历所有 QueryFilterAttribute 特性
    /// 2. 获取对应的属性信息和比较值
    /// 3. 根据 Comparison 和 FilterCondition 生成相应的表达式
    /// 4. 处理特殊条件(如日期范围、false值包含null等)
    /// </remarks>
    private static IEnumerable<Expression> HandleField(
        List<ParameterExpression> parameters,
        Func<QueryFilterAttribute, PropertyInfo?> propertyFunc,
        Func<QueryFilterAttribute, object?> valueFunc,
        IEnumerable<QueryFilterAttribute> attributes,
        object? selfValue
    )
    {
        foreach (var attr in attributes)
        {
            var property = propertyFunc(attr);
            var value = valueFunc(attr);
            if (property == null)
            {
                continue;
            }

            // 确定使用哪个参数表达式
            var parameter =
                parameters.Count == 1
                    ? parameters[0]
                    : parameters.Find(x => x.Type == attr.EntityType);
            if (parameter == null)
            {
                continue;
            }

            // 创建成员访问表达式
            Expression memberExpr = Expression.Property(parameter, property);

            // 检查是否应该跳过此条件
            if (selfValue == null || ShouldSkip(selfValue, attr.Condition, attr.ConditionValue))
            {
                continue;
            }

            // 处理日期加一天的情况
            if (attr.EndAddDay && value is DateTime end)
            {
                value = end.AddDays(1);
            }

            // 处理按天过滤的情况
            if (attr.FilterInDay && value is DateTime filterDay)
            {
                var left = !property.PropertyType.IsNullableType()
                    ? Expression.Convert(memberExpr, typeof(DateTime?))
                    : memberExpr;
                yield return DateRangeFilter(left, filterDay);
                continue;
            }

            // 处理false值包含null的情况
            if (value is false && attr.FalseHasNull)
            {
                var right1 = Expression.Convert(Expression.Constant(value), property.PropertyType);
                var right2 = Expression.Convert(Expression.Constant(null), property.PropertyType);
                var equalComparison1 = Expression.Equal(memberExpr, right1);
                var equalComparison2 = Expression.Equal(memberExpr, right2);

                yield return Expression.OrElse(equalComparison1, equalComparison2);
                continue;
            }

            // 创建右侧表达式
            Expression right;
            if (
                attr.Comparison != Comparison.Contains
                && value != null
                && property.PropertyType != value.GetType()
            )
            {
                right = Expression.Convert(Expression.Constant(value), property.PropertyType);
            }
            else
            {
                right = Expression.Constant(value);
            }

            // 根据比较方式生成不同的表达式
            yield return attr.Comparison switch
            {
                Comparison.Equal => Expression.Equal(memberExpr, right),
                Comparison.Gt => Expression.GreaterThan(memberExpr, right),
                Comparison.GtOrEqual => Expression.GreaterThanOrEqual(memberExpr, right),
                Comparison.Lt => Expression.LessThan(memberExpr, right),
                Comparison.LtOrEqual => Expression.LessThanOrEqual(memberExpr, right),
                Comparison.NotEqual => Expression.NotEqual(memberExpr, right),
                Comparison.Contains => CreateContainsExpression(
                    memberExpr,
                    attr.Condition == FilterCondition.RightAny ? attr.ConditionValue : value,
                    attr.Condition
                ),
                Comparison.SplitOrContains => CreateSplitOrContains(
                    memberExpr,
                    value,
                    attr.SplitOrContainsOtherSeparators
                ),
                _ => throw new NotImplementedException(
                    $"Comparison '{attr.Comparison}' not implemented."
                ),
            };
        }
    }

    /// <summary>
    /// 创建日期范围过滤表达式,过滤指定日期当天的数据
    /// </summary>
    /// <param name="left">左侧表达式(日期字段)</param>
    /// <param name="filterDay">要过滤的日期</param>
    /// <returns>日期范围过滤表达式,形如:<![CDATA[date >= start && date < end]]></returns>
    private static BinaryExpression DateRangeFilter(Expression left, DateTime filterDay)
    {
        DateTime? start = filterDay.Date;
        DateTime? end = start.Value.AddDays(1);

        return Expression.AndAlso(
            Expression.GreaterThanOrEqual(left, Expression.Constant(start, typeof(DateTime?))),
            Expression.LessThan(left, Expression.Constant(end, typeof(DateTime?)))
        );
    }

    /// <summary>
    /// 字符串HashSet的Contains方法的懒加载引用
    /// 用于优化字符串集合的包含关系检查
    /// </summary>
    private static readonly Lazy<MethodInfo> StringHashSetContainsMethod = new(
        () =>
            typeof(HashSet<string>).GetMethod(
                "Contains",
                BindingFlags.Public | BindingFlags.Instance
            ) ?? throw new NotSupportedException("not supported 'Contains' method")
    );

    /// <summary>
    /// 字符串Contains方法的缓存
    /// 用于优化字符串的包含关系检查
    /// </summary>
    private static readonly Lazy<MethodInfo> StringContainsMethod = new(
        () =>
            typeof(string).GetMethod("Contains", [typeof(string)])
            ?? throw new NotSupportedException("not supported string 'Contains' method")
    );

    /// <summary>
    /// Enumerable.Contains方法的缓存
    /// 用于优化集合的包含关系检查
    /// Key: 元素类型
    /// Value: 对应的 Contains 方法信息
    /// </summary>
    private static readonly ConcurrentDictionary<Type, MethodInfo> EnumerableContainsMethodCache =
        new();

    /// <summary>
    /// 获取Enumerable.Contains方法
    /// </summary>
    /// <param name="elementType">集合元素类型</param>
    /// <returns>Contains方法信息</returns>
    /// <exception cref="NotSupportedException">当找不到对应的Contains方法时抛出</exception>
    private static MethodInfo GetEnumerableContainsMethod(Type elementType)
    {
        return EnumerableContainsMethodCache.GetOrAdd(
            elementType,
            type =>
                typeof(Enumerable)
                    .GetMethods()
                    .FirstOrDefault(m => m.Name == "Contains" && m.GetParameters().Length == 2)
                    ?.MakeGenericMethod(type)
                ?? throw new NotSupportedException(
                    $"not supported Enumerable 'Contains' method for type {type}"
                )
        );
    }

    /// <summary>
    /// 创建包含关系的表达式,支持字符串包含和集合包含
    /// </summary>
    /// <param name="memberExpr">成员表达式</param>
    /// <param name="value">要检查的值</param>
    /// <param name="condition">过滤条件</param>
    /// <returns>包含关系的表达式</returns>
    /// <remarks>
    /// 支持以下情况:
    /// 1. 字符串包含:生成 string.Contains 调用
    /// 2. 集合包含:生成 Enumerable.Contains 调用
    /// 3. 可空类型:自动处理可空类型的转换
    /// </remarks>
    private static Expression CreateContainsExpression(
        Expression memberExpr,
        object? value,
        FilterCondition condition = FilterCondition.LeftAny
    )
    {
        if (condition is not (FilterCondition.LeftAny or FilterCondition.RightAny))
        {
            return Expression.Constant(false);
        }

        if (value is string)
        {
            return Expression.Call(
                memberExpr,
                StringContainsMethod.Value,
                Expression.Constant(value)
            );
        }

        if (value is IEnumerable enumerable)
        {
            // 如果属性类型是可空类型,需要先获取其基础类型
            var elementType = memberExpr.Type.IsNullableType()
                ? Nullable.GetUnderlyingType(memberExpr.Type)
                : memberExpr.Type;

            // 获取对应基础类型的 Contains 方法
            var baseContainsMethod = GetEnumerableContainsMethod(elementType!);

            // 如果属性是可空类型,需要先转换为非空类型
            var convertedMemberExpr = memberExpr.Type.IsNullableType()
                ? Expression.Convert(memberExpr, elementType!)
                : memberExpr;

            return Expression.Call(
                baseContainsMethod,
                Expression.Constant(enumerable),
                convertedMemberExpr
            );
        }

        return Expression.Constant(false);
    }

    /// <summary>
    /// 创建分割或包含表达式
    /// 如果字符串不能被空格或其他分隔符分割,则执行模糊查询;否则执行IN查询
    /// </summary>
    /// <param name="memberExpr">成员表达式</param>
    /// <param name="value">要检查的值</param>
    /// <param name="splitOrContainsOtherSeparators">用于分隔字符串的除了空格的其他分隔符</param>
    /// <returns>分割或包含表达式</returns>
    /// <remarks>
    /// 处理流程:
    /// 1. 如果输入不是字符串或为空,返回false
    /// 2. 使用空格和其他分隔符分割字符串
    /// 3. 如果分割后只有一个值,执行模糊查询
    /// 4. 否则,将分割后的值转换为HashSet,执行IN查询
    /// </remarks>
    private static Expression CreateSplitOrContains(
        Expression memberExpr,
        object? value,
        char[]? splitOrContainsOtherSeparators
    )
    {
        if (value is not string strValue || string.IsNullOrWhiteSpace(strValue))
        {
            return Expression.Constant(false);
        }

        const char splitChar = ' ';
        if (splitOrContainsOtherSeparators is { Length: > 0 })
        {
            //如果有其他分隔符,则空格替换其他分隔符
            foreach (var c in splitOrContainsOtherSeparators)
            {
                strValue = strValue.Replace(c, splitChar);
            }
        }
        var splitValues = strValue.Split(splitChar);
        if (!strValue.Contains(splitChar) && splitValues.Length <= 1)
        {
            return CreateContainsExpression(memberExpr, strValue);
        }
        var values = splitValues.Where(p => !string.IsNullOrWhiteSpace(p)).ToHashSet();

        var valuesConstant = Expression.Constant(values);

        return Expression.Call(
            instance: valuesConstant,
            method: StringHashSetContainsMethod.Value,
            arguments: Expression.Convert(memberExpr, typeof(string))
        );
    }

    /// <summary>
    /// 根据不同的条件,判断是否应该跳过当前过滤条件
    /// </summary>
    /// <param name="value">要检查的值</param>
    /// <param name="condition">过滤条件</param>
    /// <param name="comparisonValue">比较值</param>
    /// <returns>如果应该跳过,则返回true;否则返回false</returns>
    /// <remarks>
    /// 处理以下条件:
    /// 1. NotNull:值为null时跳过
    /// 2. NotNullOrEmpty:字符串为null或空时跳过
    /// 3. NotNullOrWhiteSpace:字符串为null或空白时跳过
    /// 4. LeftAny:集合为null或空时跳过
    /// 5. RightAny:数组为null或空时跳过
    /// 6. EqualValue/NotEqualValue:根据值是否相等决定是否跳过
    /// 7. 比较操作符:根据比较结果决定是否跳过
    /// </remarks>
    private static bool ShouldSkip(
        object? value,
        FilterCondition condition,
        object? comparisonValue
    )
    {
        return condition switch
        {
            FilterCondition.NotNull => value == null,
            FilterCondition.NotNullOrEmpty => value is not string str || string.IsNullOrEmpty(str),
            FilterCondition.NotNullOrWhiteSpace => value is not string str
                || string.IsNullOrWhiteSpace(str),
            FilterCondition.LeftAny => value is not ICollection collection || collection.Count == 0,
            FilterCondition.RightAny => comparisonValue is not Array array || array.Length == 0,
            FilterCondition.EqualValue => !AreEqual(value, comparisonValue),
            FilterCondition.NotEqualValue => AreEqual(value, comparisonValue),
            FilterCondition.GtValue
            or FilterCondition.LtValue
            or FilterCondition.GtOrEqualValue
            or FilterCondition.LtOrEqualValue => OperatorInvoke(value, condition, comparisonValue)
                != true,
            _ => false,
        };
    }

    /// <summary>
    /// 执行比较操作符,用于大于、小于等比较
    /// </summary>
    /// <param name="value">左侧值</param>
    /// <param name="condition">比较条件</param>
    /// <param name="conditionValue">右侧值</param>
    /// <returns>比较结果,如果无法比较则返回null</returns>
    /// <remarks>
    /// 支持以下比较操作:
    /// 1. GtValue:大于
    /// 2. LtValue:小于
    /// 3. GtOrEqualValue:大于等于
    /// 4. LtOrEqualValue:小于等于
    /// </remarks>
    private static bool? OperatorInvoke(
        object? value,
        FilterCondition condition,
        object? conditionValue
    )
    {
        if (value == null || conditionValue == null)
        {
            return null;
        }

        if (value.GetType() != conditionValue.GetType())
        {
            return null;
        }

        Expression left = Expression.Constant(value);
        Expression right;
        var currentType = value.GetType();
        if (currentType != conditionValue.GetType())
        {
            right = Expression.Convert(Expression.Constant(conditionValue), currentType);
        }
        else
        {
            right = Expression.Constant(conditionValue);
        }

        Expression<Func<bool>> initExpression = () => false;
        Expression comparisonExpression = initExpression;
        switch (condition)
        {
            // >
            case FilterCondition.GtValue:
                comparisonExpression = Expression.GreaterThan(left, right);
                break;
            // <
            case FilterCondition.LtValue:
                comparisonExpression = Expression.LessThan(left, right);
                break;
            // >=
            case FilterCondition.GtOrEqualValue:
                comparisonExpression = Expression.GreaterThanOrEqual(left, right);
                break;
            // <=
            case FilterCondition.LtOrEqualValue:
                comparisonExpression = Expression.LessThanOrEqual(left, right);
                break;
        }

        if (comparisonExpression != initExpression)
        {
            return Expression.Lambda<Func<bool>>(comparisonExpression).Compile().Invoke();
        }

        return null;
    }

    /// <summary>
    /// 判断两个对象是否相等
    /// </summary>
    /// <param name="value1">第一个对象</param>
    /// <param name="value2">第二个对象</param>
    /// <returns>如果相等则返回true,否则返回false</returns>
    /// <remarks>
    /// 处理规则:
    /// 1. 如果两个值都为null,返回false
    /// 2. 如果只有一个值为null,返回false
    /// 3. 否则使用Equals方法比较
    /// </remarks>
    private static bool AreEqual(object? value1, object? value2)
    {
        //if (value1 == null && value2 == null) return true;
        if (value1 == null || value2 == null)
        {
            return false;
        }

        return value1.Equals(value2);
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

条件过滤表达式树生成器代码解析

这段代码是一个用于动态构建LINQ表达式树的工具类,主要用于根据请求参数自动生成查询条件。以下是详细解析:

主要功能

  1. 动态构建查询条件:根据请求参数中的属性及其特性(Attribute),自动生成LINQ表达式树,用于数据库查询或其他筛选操作。

  2. 支持多种实体类型:提供了1-5个实体类型的泛型方法重载,可以同时为多个实体类型生成联合查询条件。

  3. 灵活的过滤条件:支持多种比较操作(等于、大于、小于、包含等)和过滤条件(非空、非空白等)。

核心组件

1. 属性缓存

使用ConcurrentDictionary缓存类型的属性信息,提高反射性能:

private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PropertyCache = new();

2. 主要方法

  • GenerateConditionExpressionTree<T, TRequest>:单实体版本
  • GenerateConditionExpressionTree<T, T2, TRequest>:双实体版本
  • 最多支持5个实体类型的联合查询

3. 核心处理流程

  1. 创建参数表达式:为每个实体类型创建参数表达式(如x => x.Property中的x)

  2. 处理请求参数属性

    • 获取带有QueryFilterAttribute特性的属性
    • 根据特性配置生成对应的条件表达式
  3. 构建表达式树

    • 将各个条件表达式用AND连接
    • 如果没有条件,返回true表达式

关键特性

1. 比较操作支持

支持多种比较操作:

public enum Comparison
{
    Equal,          // ==
    Gt,             // >
    GtOrEqual,      // >=
    Lt,             // <
    LtOrEqual,      // <=
    NotEqual,       // !=
    Contains,       // 包含
    SplitOrContains // 分割后包含
}

2. 特殊处理

  • 日期处理:支持日期范围过滤(如某一天的数据)
  • 空值处理:可以配置false值是否包含null
  • 字符串分割:支持按空格或其他分隔符分割字符串进行模糊查询

3. 性能优化

  • 方法缓存:缓存常用的反射方法(如Contains方法)
  • 延迟加载:使用Lazy<T>延迟加载不常用的方法
  • 属性缓存:缓存类型的属性信息,避免重复反射

使用示例

假设有一个查询请求类UserQueryRequest

public class UserQueryRequest
{
    [QueryFilter(PropertyName = "Name", Comparison = Comparison.Contains)]
    public string? Name { get; set; }
    
    [QueryFilter(PropertyName = "Age", Comparison = Comparison.GtOrEqual)]
    public int? MinAge { get; set; }
}

使用方式:

var request = new UserQueryRequest { Name = "John", MinAge = 18 };
var expression = GenerateConditionExpressionTree<User, UserQueryRequest>(request);
// 生成的表达式相当于:x => x.Name.Contains("John") && x.Age >= 18

总结

这段代码是一个强大的动态查询构建工具,它:

  1. 通过反射和表达式树技术实现了灵活的查询条件构建
  2. 支持多种比较操作和复杂条件处理
  3. 具有良好的性能优化
  4. 可以简化后端服务中常见的动态查询需求

特别适合在需要根据前端传入参数动态构建查询条件的场景中使用,如高级搜索、数据筛选等功能。

评论加载中...