使用reflection比较对象属性

我有两个类Address和Employee如下:

public class Address { public string AddressLine1 { get; set; } public string AddressLine2 { get; set; } public string City { get; set; } public string State { get; set; } public string Zip { get; set; } } public class Employee { public string FirstName { get; set; } public string MiddleName { get; set; } public string LastName { get; set; } public Address EmployeeAddress { get; set; } } 

我有两个员工实例如下:

  var emp1Address = new Address(); emp1Address.AddressLine1 = "Microsoft Corporation"; emp1Address.AddressLine2 = "One Microsoft Way"; emp1Address.City = "Redmond"; emp1Address.State = "WA"; emp1Address.Zip = "98052-6399"; var emp1 = new Employee(); emp1.FirstName = "Bill"; emp1.LastName = "Gates"; emp1.EmployeeAddress = emp1Address; var emp2Address = new Address(); emp2Address.AddressLine1 = "Gates Foundation"; emp2Address.AddressLine2 = "One Microsoft Way"; emp2Address.City = "Redmond"; emp2Address.State = "WA"; emp2Address.Zip = "98052-6399"; var emp2 = new Employee(); emp2.FirstName = "Melinda"; emp2.LastName = "Gates"; emp2.EmployeeAddress = emp2Address; 

现在,我该如何编写一个方法来比较这两个雇员并返回具有不同值的属性列表。 所以在这个例子中我希望结果是FirstName和Address.AddressLine1。

您不一定需要reflection来执行比较。 您可以编写一个比较器类,它接受两个Employee或Address实例,并比较每个应匹配的字段。 对于任何不匹配的元素,您可以将字符串(或PropertyInfo )元素添加到某个列表以返回给调用者。

是返回PropertyInfoMemberInfo还是仅返回字符串取决于调用者需要对结果执行的操作。 如果您确实需要访问包含差异的字段, PropertyInfo/MemberInfo可能会更好 – 但只是报告差异,字符串就足够了。

reflection的主要价值在于编写一个通用对象比较器,它可以获取任何类型对象的两个实例并比较它们的公共字段和属性。 这有助于避免一遍又一遍地编写重复比较代码 – 但这似乎不是你所处的情况。

编辑,使它与你的课程相匹配就像LBushskin所说的那样,你并不喜欢这样做。 这不是最快的方法! 如果你想购买,试试这个:

  public static List GetDifferences(Employee test1, Employee test2) { List differences = new List(); foreach (PropertyInfo property in test1.GetType().GetProperties()) { object value1 = property.GetValue(test1, null); object value2 = property.GetValue(test2, null); if (!value1.Equals(value2)) { differences.Add(property); } } return differences; } 
 public IEnumerable GetNotEqualsProperties(Employee emp1, Employee emp2) { Type employeeType = typeof (Employee); var properies = employeeType.GetProperties(); foreach (var property in properies) if(!property.GetValue(emp1, null).Equals(property.GetValue(emp2, null))) //TODO: check for null yield return property; } 

对于复杂属性,您必须重写Equals方法

 public class Address { public string AddressLine1 { get; set; } public string AddressLine2 { get; set; } public string City { get; set; } public string State { get; set; } public string Zip { get; set; } public override bool Equals(object obj) { if (obj as Address == null) return false; return ((Address) obj).AddressLine1.Equals(AddressLine1); } } 

无需反思。 当然,这个例子返回一个带有属性名称的字符串……如果你需要实际的PropertyInfo对象,事情会变得更加困难,但不是很多。

 public static IEnumerable DiffEmployees (Employee one, Employee two) { if(one.FirstName != two.FirstName) yield return "FirstName"; if(one.LastName != two.LastName) yield return "LastName"; if(one.Address.AddressLine1 != two.Address.AddressLine1) yield return "Address.AddressLine1"; // And so on. }