/// <summary> /// Compare a dictionary /// </summary> /// <param name="object1"></param> /// <param name="object2"></param> /// <param name="breadCrumb"></param> private void CompareIDictionary(object object1, object object2, string breadCrumb) { _parents.Add(object1); _parents.Add(object2); IDictionary iDict1 = object1 as IDictionary; IDictionary iDict2 = object2 as IDictionary; if (iDict1 == null) //This should never happen, null check happens one level up { throw new ArgumentNullException("object1"); } if (iDict2 == null) //This should never happen, null check happens one level up { throw new ArgumentNullException("object2"); } //Objects must be the same length if (iDict1.Count != iDict2.Count) { Differences.Add(string.Format("object1{0}.Count != object2{0}.Count ({1},{2})", breadCrumb, iDict1.Count, iDict2.Count)); if (Differences.Count >= MaxDifferences) { return; } } IDictionaryEnumerator enumerator1 = iDict1.GetEnumerator(); IDictionaryEnumerator enumerator2 = iDict2.GetEnumerator(); while (enumerator1.MoveNext() && enumerator2.MoveNext()) { string currentBreadCrumb = AddBreadCrumb(breadCrumb, "Key", string.Empty, -1); bool object1IsParent = enumerator1.Key != null && (enumerator1.Key == object1 || _parents.Contains(enumerator1.Key)); bool object2IsParent = enumerator2.Key != null && (enumerator2.Key == object2 || _parents.Contains(enumerator2.Key)); //Skip keys where both have been previously visited if (!((enumerator1.Key == null) || (!IsClass(enumerator1.Key.GetType())) || (!object1IsParent || !object2IsParent))) { Compare(enumerator1.Key, enumerator2.Key, currentBreadCrumb); if (Differences.Count >= MaxDifferences) { return; } } currentBreadCrumb = AddBreadCrumb(breadCrumb, "Value", string.Empty, -1); object1IsParent = enumerator1.Value != null && (enumerator1.Value == object1 || _parents.Contains(enumerator1.Value)); object2IsParent = enumerator2.Value != null && (enumerator2.Value == object2 || _parents.Contains(enumerator2.Value)); //Skip values where both have been previously visited if ((enumerator1.Value != null) && (IsClass(enumerator1.Value.GetType())) && (object1IsParent && object2IsParent)) { continue; } Compare(enumerator1.Value, enumerator2.Value, currentBreadCrumb); if (Differences.Count >= MaxDifferences) { return; } } }
/// <summary> /// Compare a dictionary /// </summary> /// <param name="object1"></param> /// <param name="object2"></param> /// <param name="breadCrumb"></param> void CompareIDictionary(object object1, object object2, string breadCrumb) { IDictionary iDict1 = object1 as IDictionary; IDictionary iDict2 = object2 as IDictionary; if (iDict1 == null) //This should never happen, null check happens one level up { throw new ArgumentNullException("object1"); } if (iDict2 == null) //This should never happen, null check happens one level up { throw new ArgumentNullException("object2"); } try { _parents.Add(object1); _parents.Add(object2); //Objects must be the same length if (iDict1.Count != iDict2.Count) { Differences.Add(string.Format("object1{0}.Count != object2{0}.Count ({1},{2})", breadCrumb, iDict1.Count, iDict2.Count)); if (Differences.Count >= MaxDifferences) { return; } } IDictionaryEnumerator enumerator1 = iDict1.GetEnumerator(); IDictionaryEnumerator enumerator2 = iDict2.GetEnumerator(); while (enumerator1.MoveNext() && enumerator2.MoveNext()) { string currentBreadCrumb = AddBreadCrumb(breadCrumb, "Key", string.Empty, -1); Compare(enumerator1.Key, enumerator2.Key, currentBreadCrumb); if (Differences.Count >= MaxDifferences) { return; } currentBreadCrumb = AddBreadCrumb(breadCrumb, "Value", string.Empty, -1); Compare(enumerator1.Value, enumerator2.Value, currentBreadCrumb); if (Differences.Count >= MaxDifferences) { return; } } } finally { _parents.Remove(object1); _parents.Remove(object2); } }
/// <summary> /// Compare two objects /// </summary> /// <param name="object1"></param> /// <param name="object2"></param> /// <param name="breadCrumb">Where we are in the object hiearchy</param> private void Compare(object object1, object object2, string breadCrumb) { //If both null return true if (object1 == null && object2 == null) { return; } //Check if one of them is null if (object1 == null) { Differences.Add(string.Format("object1{0} == null && object2{0} != null ((null),{1})", breadCrumb, cStr(object2))); return; } if (object2 == null) { Differences.Add(string.Format("object1{0} != null && object2{0} == null ({1},(null))", breadCrumb, cStr(object1))); return; } Type t1 = object1.GetType(); Type t2 = object2.GetType(); //Objects must be the same type if (t1 != t2) { Differences.Add(string.Format("Different Types: object1{0}.GetType() != object2{0}.GetType()", breadCrumb)); return; } Delegate customComparer; if (_customComparers.TryGetValue(t1, out customComparer)) { CompareWithCustomComparer(object1, object2, breadCrumb, t1, customComparer); } else if (IsIList(t1)) //This will do arrays, multi-dimensional arrays and generic lists { CompareIList(object1, object2, breadCrumb); } else if (IsIDictionary(t1)) { CompareIDictionary(object1, object2, breadCrumb); } else if (IsEnum(t1)) { CompareEnum(object1, object2, breadCrumb); } else if (IsSimpleType(t1)) { CompareSimpleType(object1, object2, breadCrumb); } else if (IsClass(t1)) { CompareClass(object1, object2, breadCrumb); } else if (IsTimespan(t1)) { CompareTimespan(object1, object2, breadCrumb); } else if (IsStruct(t1)) { CompareStruct(object1, object2, breadCrumb); } else { throw new NotImplementedException("Cannot compare object of type " + t1.Name); } }
void Compare(object object1, object object2, string breadCrumb) { if (object1 == null && object2 == null) { return; } if (object1 == null) { Differences.Add(string.Format("object1{0} == null && object2{0} != null ((null),{1})", breadCrumb, cStr(object2))); return; } if (object2 == null) { Differences.Add(string.Format("object1{0} != null && object2{0} == null ({1},(null))", breadCrumb, cStr(object1))); return; } Type t1 = object1.GetType(); Type t2 = object2.GetType(); if (t1 != t2) { Differences.Add(string.Format("Different Types: object1{0}.GetType() != object2{0}.GetType()", breadCrumb)); return; } else if (IsIList(t1)) { CompareIList(object1, object2, breadCrumb); } else if (IsIDictionary(t1)) { CompareIDictionary(object1, object2, breadCrumb); } else if (IsEnum(t1)) { CompareEnum(object1, object2, breadCrumb); } else if (IsPointer(t1)) { ComparePointer(object1, object2, breadCrumb); } else if (IsSimpleType(t1)) { CompareSimpleType(object1, object2, breadCrumb); } else if (IsClass(t1)) { CompareClass(object1, object2, breadCrumb); } else if (IsTimespan(t1)) { CompareTimespan(object1, object2, breadCrumb); } else if (IsStruct(t1)) { CompareStruct(object1, object2, breadCrumb); } else { throw new NotImplementedException("Cannot compare object of type " + t1.Name); } }