赞
踩
实现类:
- public static class LinqHepler
- {
- /// <summary>
- /// 根据单个字段动态Group
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="source"></param>
- /// <param name="propertyName"></param>
- /// <returns></returns>
- public static IEnumerable<IGrouping<object, T>> GroupByDynamic<T>(this IEnumerable<T> source, string propertyName)
- {
- var parameter = Expression.Parameter(typeof(T), "p");
- var property = Expression.Property(parameter, propertyName);
- var lambda = Expression.Lambda(typeof(Func<T, object>), Expression.Convert(property, typeof(object)), parameter);
-
- var groupByMethod = typeof(Enumerable).GetMethods()
- .Where(m => m.Name == "GroupBy" && m.GetParameters().Length == 2).First();
-
- var groupBy = groupByMethod.MakeGenericMethod(typeof(T), typeof(object));
-
- return (IEnumerable<IGrouping<object, T>>)groupBy.Invoke(null, new object[] { source, lambda.Compile() });
- }
-
- /// <summary>
- /// 多字段动态GroupBy
- /// </summary>
- /// <typeparam name="T">需要重写GetHashCode和Equals方法, 因为类是比较引用的,而常用于GroupBy操作的匿名类是比较值的</typeparam>
- /// <param name="source"></param>
- /// <param name="propertyNames"></param>
- /// <returns></returns>
- public static IEnumerable<IGrouping<T, T>> GroupByDynamic<T>(this IEnumerable<T> source, List<string> propertyNames) where T : class
- {
- if(propertyNames.IsNullOrEmpty())
- throw new ArgumentNullException("propertyNames");
-
- var parameter = Expression.Parameter(typeof(T), "p");
- var lambda = BuildSelector<T>(parameter, propertyNames);
-
- var groupByMethod = typeof(Enumerable).GetMethods()
- .Where(m => m.Name == "GroupBy" && m.GetParameters().Length == 2).First();
-
- var groupBy = groupByMethod.MakeGenericMethod(typeof(T), typeof(T));
-
- return (IEnumerable<IGrouping<T, T>>)groupBy.Invoke(null, new object[] { source, lambda });
- }
-
- private static Func<T, T> BuildSelector<T>(ParameterExpression param, List<string> propertyNames)
- {
- var memberBindings = new List<MemberBinding>(propertyNames.Count);
- foreach (var propertyName in propertyNames)
- {
- var expressionProperty = Expression.Property(param, propertyName);
- memberBindings.Add(Expression.Bind(typeof(T).GetProperty(propertyName), expressionProperty));
- }
- var memberInit = Expression.MemberInit(Expression.New(typeof(T)), memberBindings);
-
- var lambda = Expression.Lambda<Func<T, T>>(memberInit, param);
- return lambda.Compile();
- }
- }

使用方式:
- var people = new List<Person>
- {
- new Person { Name = "Alice",Six="男", Age = 30 },
- new Person { Name = "Alice",Six="男", Age = 20 },
- new Person { Name = "Bob",Six="男", Age = 30 },
- new Person { Name = "Bob",Six="男", Age = 25 },
- new Person { Name = "Charlie",Six="男", Age = 25 },
- new Person { Name = "Charlie",Six="男", Age = 25 }
- };
-
- var groupFileds = new List<string>() { "Name", "Six" };
- var groupedByName = people
- .GroupByDynamic(groupFileds)
- .Select(t =>
- {
- var model = new Person()
- {
- Name = t.First().Name,
- Six = t.First().Six,
- Age = t.Sum(p => p.Age),
- Details = t.ToList(),
- };
- return model;
- })
- .ToList();
- //需要重写GetHashCode和Equals方法, 因为类是比较引用的,而常用于GroupBy操作的匿名类是比较值的
- public class Person
- {
- public string? Name { get; set; }
- public string? Six { get; set; }
- public int Age { get; set; }
- public override int GetHashCode()
- {
- return $"{Name},{Six},{Age}".GetHashCode(); //需要用来分组的字段,或者全部字段
- }
- public override bool Equals(object? obj)
- {
- if (obj == null)
- return false;
- if(!(obj is Person))
- return false;
- return this.GetHashCode() == obj.GetHashCode();
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。