I have a requirement in my current project at work where I have to deep compare two complex objects in .Net and potentially need to return the differences between the two.
The complex class looks similar to this sample Organisation class
public class Organisation
{
public IEnumerable<Department> Departments { get; set; }
// Many other properties
}
public class Department
{
public IEnumerable<Employee> Employees { get; set; }
// Many other properties
}
public class Employee
{
public Address Address { get; set; }
// There are more than other 10 properties
}
public class Address
{
// Many properties
}
A colleague already wrote his own code to compare any two complex objects. However the solution requires each class to implement a Compare method where you have specify which properties you want to compare between the objects. You would have to do the same for all the complex object properties within those classes. Also if the class contains a collection property, and the lists are the same between two objects but in different order, it might not work well. He suggested looking into this library called CompareNETObjects so I thought I’d give it a go.
CompareNETObjects uses reflection to deep compare two objects. It also allows comparing two collections in different order though this might have a performance impact.
To compare the two Organisation objects from above, I have a function in the Organisation class which looks like this
public bool EqualsTo(Organisation organisation)
{
var compareLogic = new CompareLogic();
compareLogic.Config.IgnoreCollectionOrder = true;
compareLogic.Config.TreatStringEmptyAndNullTheSame = true;
ComparisonResult result = compareLogic.Compare(this, organisation);
return result.AreEqual;
}
The ComparisonResult class provides details of all the differences. This allows me to not only comparing if two objects are different but also able to return all the differences.
I have a new model that the EqualsTo method returns which includes all the differences.
public class ObjectsComparisonResult
{
public bool AreEqual { get; set; }
public IEnumerable<PropertyDifference> PropertyDifferences { get; set; };
}
public class PropertyDifference
{
public string PropertyName { get; set; }
public string OriginalValue { get; set; }
public string NewValue { get; set; }
}
So now my EqualsTo method would look like
public ObjectsComparisonResult EqualsTo(Organisation organisation)
{
var compareLogic = new CompareLogic();
compareLogic.Config.IgnoreCollectionOrder = true;
compareLogic.Config.IgnoreObjectTypes = true;
compareLogic.Config.TreatStringEmptyAndNullTheSame = true;
ComparisonResult result = compareLogic.Compare(this, organisation);
return new ObjectsComparisonResult
{
AreEqual = result.AreEqual,
PropertyDifferences = result.AreEqual ?
Enumerable.Empty<PropertyDifference>() :
result.Differences.Select(x => new PropertyDifference
{
PropertyName = x.PropertyName,
OriginalValue = x.Object1Value,
NewValue = x.Object2Value
})
};
}
I have a lot of unit tests to verify that this library works as expected and it seems to work well. I have same Organisation objects with Employees and Departments collections in different order and the test results are correct.
This library is great but I would implement the typical Equals() or manually compare each property to find differences for simple classes and only use it for complex classes. As this library uses Reflection, it would have a performance impact if using it for all classes.