1

I have two objects with the same properties. What I need is the list of properties having a difference in values. Consider the following classes (there can be many properties but they will always be the same in both the classes). In the example, I have two objects with a difference in lastname and address. So, I need a list that contains the property name along with the old and new values.

public class A
{
    public string ColumnName { get; set; }
    public string oldValue { get; set; }
    public string newValue { get; set; }
}
public class B
{
    public string ColumnName { get; set; }
    public string oldValue { get; set; }
    public string newValue { get; set; }
}
public class C
{
    public string ColumnName { get; set; }
    public string oldValue { get; set; }
    public string newValue { get; set; }
}
A objA = new A();
objA.firstName = "XYZ";
objA.lastName = "ABC";
objA.address = "123";
B objB = new B();
objB.firstName = "XYZ";
objB.lastName = "ABCD";
objB.address = "456";
List<C> listObj = new List<C>();
//Here I need a list of the columns having different value. For example this should be the result after comparison.
listObj.Add(new C{ColumnName = "lastName", oldValue = "ABC", newValue = "ABCD"});
listObj.Add(new C{ColumnName = "address", oldValue = "123", newValue = "456"});

Is there a way this can be achieved (preferably LINQ but not necessary)?

EDIT: For those looking for a solution, this is exactly what I was looking for: CompareNETObjects

Milo
  • 3,365
  • 9
  • 30
  • 44
astm1982
  • 145
  • 13
  • You would need to use reflection to compare properties by name – Johnathan Barclay Nov 13 '19 at 11:50
  • This can be done using Reflection. Get the property names, invoke them to get the values, compare and then act. – JayV Nov 13 '19 at 11:50
  • This question with its answers will help you a lot: https://stackoverflow.com/questions/506096/comparing-object-properties-in-c-sharp – JayV Nov 13 '19 at 11:52
  • Use a left outer join. The null items are the ones that do not match. You will need to do A Join B and B join A as two separate queries. – jdweng Nov 13 '19 at 11:54

1 Answers1

1

The result of this LINQ is list of C class instances with different property name, old object value and new object value.

typeof(A).GetProperties().OrderBy(p => p.Name)
    .Zip(typeof(B).GetProperties().OrderBy(p => p.Name),
    ((aInfo, bInfo) => !aInfo.GetValue(objA).Equals(bInfo.GetValue(objB))
        ? new C() 
        { 
            ColumnName = aInfo.Name,
            oldValue = aInfo.GetValue(objA).ToString(), 
            newValue = bInfo.GetValue(objB).ToString()
        }
        : null))
    .Where(x => !(x is null)).ToList();

More generall with anonymous class instead of C.

typeof(A).GetProperties().OrderBy(p => p.Name)
    .Zip(typeof(B).GetProperties().OrderBy(p => p.Name),
    ((aInfo, bInfo) => !aInfo.GetValue(objA).Equals(bInfo.GetValue(objB))
        ? new
        { 
            ColumnName = aInfo.Name,
            oldValue = aInfo.GetValue(objA), 
            newValue = bInfo.GetValue(objB)
        }
        : null))
    .Where(x => !(x is null)).ToList();
  • This also works in case someone is not interested in third party libraries. The only change I had to do was .Where(x => x!=null).ToList(); Weird but worked afterwards. – astm1982 Nov 15 '19 at 13:42