Comparing Object Properties Using Reflection

I have two Address and Employee classes:

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; } } 

I have two instances of employees:

  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; 

Now, how can I write a method that compares these two employees and returns a list of properties that have different values. Therefore, in this example, I would like the result to be the first name and address of .AddressLine1.

+5
source share
5 answers

You do not have to reflect to perform the comparison. You can write a comparison class that takes two instances of Employee or Address and compares each field that should match. For all that do not match, you can add an element (or PropertyInfo ) to some list to return to the caller.

Whether you PropertyInfo , MemberInfo , or just the string depends on what the caller should do with the result. If you really need to visit fields containing differences, PropertyInfo/MemberInfo might be better, but just reporting the differences, that the string is likely enough.

The main meaning of reflection will be to write a general purpose object mapping that can take two instances of any object and compare their public fields and properties. This helps to avoid reusing repeated code comparisons, but this is not like when you are.

+1
source

As L. Bushskin said, you do not need to do this. This is not the fastest way! Buy it if you want, try this:

  public static List<PropertyInfo> GetDifferences(Employee test1, Employee test2) { List<PropertyInfo> differences = new List<PropertyInfo>(); 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; } 
+11
source

Here is a typical and recursive solution based on Oscar Chiellina .

I also posted this code as a hist , so you can check the latest version or tag it with an asterisk / clone / fork :)

 using System; using System.Collections.Generic; using System.Linq; using System.Reflection; protected List<KeyValuePair<Type, PropertyInfo>> RecrusiveReflectionCompare<T>(T first, T second) where T : class { var differences = new List<KeyValuePair<Type, PropertyInfo>>(); var parentType = first.GetType(); void CompareObject(object obj1, object obj2, PropertyInfo info) { if (!obj1.Equals(obj2)) { differences.Add(new KeyValuePair<Type, PropertyInfo>(parentType, info)); } } foreach (PropertyInfo property in parentType.GetProperties()) { object value1 = property.GetValue(first, null); object value2 = property.GetValue(second, null); if (property.PropertyType == typeof(string)) { if (string.IsNullOrEmpty(value1 as string) != string.IsNullOrEmpty(value2 as string)) { CompareObject(value1, value2, property); } } else if (property.PropertyType.IsPrimitive) { CompareObject(value1, value2, property); } else { if (value1 == null && value2 == null) { continue; } differences.Concat(RecrusiveReflectionCompare(value1, value2)); } } return differences; } 
+1
source

No need to reflect. Of course, this example returns a string with property names ... if you need the actual PropertyInfo object, everything will be a little more complicated, but not much.

 public static IEnumerable<string> 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. } 
0
source
 public IEnumerable<PropertyInfo> 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; } 

And for complex properties you have to override the Equals method

 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); } } 
0
source

Source: https://habr.com/ru/post/1304914/


All Articles