2009-10-31 1 views
4

Можно создать дубликат:
Comparing object properties in c#Как сравнить поля/свойства между POCOs?

Допустим, у меня есть ПОКО:

public class Person 
{ 
    public string Name { get; set; } 
    public DateTime DateOfBirth { get; set; } 
    public IList<Person> Relatives { get; set; } 
} 

Я хочу, чтобы сравнить два экземпляра Person, чтобы увидеть, если они равны друг друга. Естественно, я бы сравнил Name, DateOfBirth и коллекцию Relatives, чтобы увидеть, равны ли они. Тем не менее, это потребует от меня переопределения Equals() для каждого POCO и ручной записи сравнения для каждого поля.

Мой вопрос в том, как я могу написать общую версию этого, поэтому мне не нужно делать это для каждого POCO?

ответ

4

Если вы не беспокоитесь о производительности, вы могли бы использовать отражение в функции полезности перебрать каждое поле и сравнить их значение.

using System; 
using System.Reflection; 


public static class ObjectHelper<t> 
{ 
    public static int Compare(T x, T y) 
    { 
     Type type = typeof(T); 
     var publicBinding = BindingFlags.DeclaredOnly | BindingFlags.Public; 
     PropertyInfo[] properties = type.GetProperties(publicBinding); 
     FieldInfo[] fields = type.GetFields(publicBinding); 
     int compareValue = 0; 


     foreach (PropertyInfo property in properties) 
     { 
      IComparable valx = property.GetValue(x, null) as IComparable; 
      if (valx == null) 
       continue; 
      object valy = property.GetValue(y, null); 
      compareValue = valx.CompareTo(valy); 
      if (compareValue != 0) 
       return compareValue; 
     } 
     foreach (FieldInfo field in fields) 
     { 
      IComparable valx = field.GetValue(x) as IComparable; 
      if (valx == null) 
       continue; 
      object valy = field.GetValue(y); 
      compareValue = valx.CompareTo(valy); 
      if (compareValue != 0) 
       return compareValue; 
     } 
    return compareValue; 
    } 
} 
+0

Спасибо, я постараюсь ваш код из. –

+0

Хм, я попробовал, но массивы 'properties' и' fields' пусты. –

+0

Понял почему. Удалите переменную publicBinding или используйте другой тип перечисления, чем DeclaredOnly или Public. –

1

Можно использовать отражение, чтобы сделать это в общем, но имеет недостатки производительности и сложности. Намного лучше реализовать Equals и GetHashCode вручную, чтобы вы получили ожидаемые результаты.

См Should I Overload == Operator?

1

Внедрение Equals() и GetHashCode() не так много хлопот.

public override bool Equals(object obj) 
{ 
    if (ReferenceEquals(this, obj) return true; 
    if (!(obj is Person)) return false; 

    var other = (Person) obj; 
    return this == other; 
} 

public override int GetHashCode() 
{ 
    return base.GetHashCode(); 
} 

См Using Equals/GetHashCode Effectively

+0

Я в замешательстве. Ваш пример - это просто поведение по умолчанию Equals(). И это может быть не так много хлопот для одного класса, но когда вам нужно добавить кучу кода шаблона в 50+ классов, это становится проблемой. –

Смежные вопросы