I think the answer of Big T was quite good but the deep comparison was missing, so I tweaked it a little bit:
using System.Collections.Generic;
using System.Reflection;
/// Comparison class.
public static class Compare
{
/// Compare the public instance properties. Uses deep comparison.
/// The reference object.
/// The object to compare.
/// Ignore property with name.
/// Type of objects.
/// True if both objects are equal, else false.
public static bool PublicInstancePropertiesEqual(T self, T to, params string[] ignore) where T : class
{
if (self != null && to != null)
{
var type = self.GetType();
var ignoreList = new List(ignore);
foreach (var pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (ignoreList.Contains(pi.Name))
{
continue;
}
var selfValue = type.GetProperty(pi.Name).GetValue(self, null);
var toValue = type.GetProperty(pi.Name).GetValue(to, null);
if (pi.PropertyType.IsClass && !pi.PropertyType.Module.ScopeName.Equals("CommonLanguageRuntimeLibrary"))
{
// Check of "CommonLanguageRuntimeLibrary" is needed because string is also a class
if (PublicInstancePropertiesEqual(selfValue, toValue, ignore))
{
continue;
}
return false;
}
if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)))
{
return false;
}
}
return true;
}
return self == to;
}
}