Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare two objects for properties with different values

I need to create a generic method, which will take two objects (of same type), and return list of properties which have different values. As my requirement is bit different I don't think this as duplicate.

public class Person
{
   public string Name {get;set;}
   public string Age {get;set;}
}

Person p1 = new Person{FirstName = "David", Age = 33}
Person p2 = new Person{FirstName = "David", Age = 44}

var changedProperties = GetChangedProperties(p1,p2);

The code explains the requirement:

public List<string> GetChangedProperties(object A, object B)
{
    List<string> changedProperties = new List<string>();
   //Compare for changed values in properties 
   if(A.Age != B.Age)
   {
       //changedProperties.Add("Age");
   } 
   //Compare other properties
   ..
   ..
   return changedProperties;
}

Should consider following:

  1. Generic - Should be able to compare any type of objects (with same class)
  2. Performance
  3. Simple

Is there any libraries available out of the box there?

Can I achieve this using AutoMapper?

like image 629
Rahul Avatar asked Mar 15 '17 12:03

Rahul


1 Answers

I improved a little on Krishnas answer:

public List<string> GetChangedProperties<T>(object A, object B)
{
    if (A != null && B != null)
    {
        var type = typeof(T);
        var allProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        var allSimpleProperties = allProperties.Where(pi => pi.PropertyType.IsSimpleType());
        var unequalProperties =
               from pi in allSimpleProperties
               let AValue = type.GetProperty(pi.Name).GetValue(A, null)
               let BValue = type.GetProperty(pi.Name).GetValue(B, null)
               where AValue != BValue && (AValue == null || !AValue.Equals(BValue))
               select pi.Name;
        return unequalProperties.ToList();
    }
    else
    {
        throw new ArgumentNullException("You need to provide 2 non-null objects");
    }
}

because it wasn't working for me. This one does and the only other thing you need to make it work is the IsSimpleType()-Extension Method that I adapted from this answer here (I only converted it into an extension method).

public static bool IsSimpleType(this Type type)
{
    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
    {
        // nullable type, check if the nested type is simple.
        return type.GetGenericArguments()[0].IsSimpleType();
    }
    return type.IsPrimitive
      || type.IsEnum
      || type.Equals(typeof(string))
      || type.Equals(typeof(decimal));
}
like image 115
robkrueger Avatar answered Oct 05 '22 07:10

robkrueger