C#根据传入的字段名,动态分组,支持多字段分组

 

分组方法DynamicLinqExtensions:

复制代码
/// <summary>
/// 动态构建分组表达式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="propertyNames">上限最大7个元素</param>
/// <returns></returns>
public static Expression<Func<T, object>> GroupByExpression<T>(string[] propertyNames)
{
    var properties = propertyNames.Select(name => typeof(T).GetProperty(name)).ToArray();
    var propertyTypes = properties.Select(p => p.PropertyType).ToArray();
    var tupleTypeDefinition = typeof(Tuple).Assembly.GetType("System.Tuple`" + properties.Length);
    var tupleType = tupleTypeDefinition.MakeGenericType(propertyTypes);
    var constructor = tupleType.GetConstructor(propertyTypes);
    var param = Expression.Parameter(typeof(T), "item");
    var body = Expression.New(constructor, properties.Select(p => Expression.Property(param, p)));
    var expr = Expression.Lambda<Func<T, object>>(body, param);
    return expr;
}

/// <summary>
/// 动态分组
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="propertyNames">任意个数元素</param>
/// <returns></returns>
public static IEnumerable<IGrouping<object[], T>> GroupByDynamic<T>(this IEnumerable<T> source, params string[] propertyNames)
{
    var parameter = Expression.Parameter(typeof(T), "item");
    var projections = propertyNames.Select(propertyName =>
        Expression.PropertyOrField(parameter, propertyName)
    ).ToArray();

    var body = Expression.NewArrayInit(typeof(object), projections.Cast<Expression>());
    var lambda = Expression.Lambda<Func<T, object[]>>(body, parameter);

    return source.GroupBy(lambda.Compile(), new ObjectArrayComparer());
}
复制代码

 

复制代码
// 自定义比较器,用于比较object数组  
public class ObjectArrayComparer : IEqualityComparer<object[]>
{
    public bool Equals(object[] x, object[] y)
    {
        if (x == null && y == null) return true;
        if (x == null || y == null) return false;
        if (x.Length != y.Length) return false;

        for (int i = 0; i < x.Length; i++)
        {
            if (!Equals(x[i], y[i])) return false;
        }

        return true;
    }

    public int GetHashCode(object[] obj)
    {
        unchecked
        {
            int hash = 17;
            foreach (var item in obj)
            {
                if (item != null)
                {
                    hash = hash * 23 + item.GetHashCode();
                }
            }
            return hash;
        }
    }
}
View Code
复制代码

 

posted @   SmilePastaLi  阅读(73)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示