When we do testing, we often need to compare 2 objects. The problems are:
- It is often that we don’t bother to override GetHashCode and Equals method. Laziness plays part here :) .
- We often need to ignore some properties.
There are properties that need special comparison method.
They are different types, but have a similar set of properties.
The worst case is you are comparing against anonymous / upcasted objects.
Once again, reflection solves the problem easily for us.
bool AreEqual(object obj1, object obj2, ICollection<string> lstException,
IDictionary<string, Func<object, object, bool>> methodDictionary)
{
var type1 = obj1.GetType();
var arrProperty = type1.GetProperties();
foreach (var property in arrProperty)
{
if (lstException != null && lstException.Contains(property.Name))
continue;
var value1 = property.GetValue(obj1, null);
var value2 = property.GetValue(obj2, null);
if ((value1 == null && value2 != null) || (value1 != null && value2 == null))
return false;
if (value1 == null) continue;
if (methodDictionary == null || !methodDictionary.ContainsKey(property.Name))
{
if (!value1.Equals(value2))
return false;
}
else
{
var method = methodDictionary[property.Name];
if (method != null)
return method(value1, value2);
return false;
}
}
return true;
}
Example of usage:
void TestCompare()
{
var object1 = new {Isbn = 10203299399, Name = "Book One", Price = 300, Author = new {ID = 123, Name = "Gray"}};
var object2 = new {Isbn = 10203299399, Name = "Book One", Price = 230, Author = new {ID = 123, Name = "Gray"}};
var result=AreEqual(object1, object2, new List<string> {"Price"}, new Dictionary<string, Func<object, object, bool>>
{
{"Author",(obj1,obj2)=>object1.Author.ID==object2.Author.ID}
});
Console.WriteLine(result.ToString());
}
In the above method, we compare 2 anonymous objects, ignore Price property, and compare Author property based on their ID.
I often call this method inside nUnit’s Assert.IsTrue .