C# 使用IEqualityComparer接口实现集合对象的动态分组
速度可能有点慢,毕竟使用的是反射。。。
分组效果
代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Linq.Expressions; 5 using System.Reflection; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace ConsoleApp1 10 { 11 internal class Program 12 { 13 private static void Main(string[] args) 14 { 15 var list = new List<Student>(); 16 var stu1 = new Student() { Id = 1, Name = "张三", Age = 18 }; 17 var stu2 = new Student() { Id = 1, Name = "张三", Age = 18 }; 18 var stu3 = new Student() { Id = 2, Name = "李四", Age = 18 }; 19 var stu4 = new Student() { Id = 3, Name = "李四", Age = 18 }; 20 var stu5 = new Student() { Id = 1, Name = "王五", Age = 18 }; 21 var stu6 = new Student() { Id = 1, Name = "王五", Age = 18 }; 22 list.Add(stu1); 23 list.Add(stu2); 24 list.Add(stu3); 25 list.Add(stu4); 26 list.Add(stu5); 27 list.Add(stu6); 28 29 var refer = new ObjectComparer<Student>(new string[] { "Name", "Id" }); 30 var groups = list.GroupBy(c => c, refer); 31 foreach (var g in groups) 32 { 33 Console.WriteLine($"key: {g.Key}"); 34 foreach (var s in g) 35 { 36 Console.WriteLine($" {s.Id}==={s.Name}==={s.Age}"); 37 } 38 } 39 } 40 41 private class ObjectComparer<T> : IEqualityComparer<T> 42 { 43 private PropertyInfo[] _propertyInfos; 44 45 public ObjectComparer(IEnumerable<string> propertyNames) 46 { 47 var properties = typeof(T).GetProperties(); 48 var list = new List<PropertyInfo>(); 49 foreach (var p in properties) 50 { 51 if (propertyNames.Contains(p.Name)) 52 { 53 list.Add(p); 54 } 55 } 56 _propertyInfos = list.ToArray(); 57 } 58 59 public bool Equals(T x, T y) 60 { 61 foreach (var p in _propertyInfos) 62 { 63 var type = p.PropertyType; 64 65 //使用动态类型,在运行的时候调用对象的Equal方法 66 dynamic value1 = x.GetType().GetProperty(p.Name).GetValue(x); 67 dynamic value2 = y.GetType().GetProperty(p.Name).GetValue(y); 68 if (value1 != value2) 69 { 70 return false; 71 } 72 } 73 return true; 74 } 75 76 public int GetHashCode(T obj) 77 { 78 var hash = _propertyInfos.Select(p => p.GetValue(obj).GetHashCode()) 79 .Aggregate((x, y) => x & y); 80 return hash; 81 } 82 } 83 84 /// <summary> 85 /// 实现了相等性接口 86 /// </summary> 87 private class Student 88 { 89 public int Age { get; set; } 90 91 public int Id { get; set; } 92 93 public string Name { get; set; } 94 95 //public bool Equals(Student other) 96 //{ 97 // if (other == null) { return false; } 98 99 // if (ReferenceEquals(this, other)) { return true; }; 100 101 // return (Id, Age, Name) == (other.Id, other.Age, other.Name); 102 //} 103 104 //public override int GetHashCode() 105 //{ 106 // return (Id, Age, Name).GetHashCode(); 107 //} 108 109 //public override string ToString() 110 //{ 111 // return Name; 112 //} 113 } 114 } 115 }