private static bool Compare(object obj1, object obj2, ObjectReferenceDictionary recursiveObjects) { bool equals; if ((obj1 == null) || (obj2 == null)) { equals = ((obj1 == null) && (obj2 == null)); if (!equals) { var type = (obj1 ?? obj2).GetType(); LogFailedComparison("at least one of the instances is null", type, $"obj1 is{(obj1 == null ? "" : "n't")} null", $"obj2 is{(obj2 == null ? "" : "n't")} null"); } } else { IFieldValueEqualityComparer comparer; if (MatchesComparer(obj1, obj2, out comparer) || AreObjectsSameType(obj1, obj2) || AreObjectsDictionaries(obj1, obj2) || AreObjectsEnumerables(obj1, obj2)) { var dictionary1 = obj1 as IDictionary; if (comparer != null) { equals = comparer.Equals(obj1, obj2); } else if (obj1 is byte[]) { var lhs = (byte[])obj1; var rhs = (byte[])obj2; equals = lhs.StructurallyEqual(rhs); } else if (dictionary1 != null) { var dictionary2 = (IDictionary)obj2; equals = AlreadyCompared(dictionary1, dictionary2, recursiveObjects) || (PerformListFieldComparison(dictionary1.Keys, dictionary2.Keys, recursiveObjects) && (PerformListFieldComparison(dictionary1.Values, dictionary2.Values, recursiveObjects))); } else if (obj1 is IEnumerable && obj1.GetType() != typeof(string)) { equals = AlreadyCompared(obj1, obj2, recursiveObjects) || PerformListFieldComparison((IEnumerable)obj1, obj2 as IEnumerable, recursiveObjects); } else if (ShouldFieldHaveValueSemanticEqualityPerformed(obj1.GetType())) { equals = AlreadyCompared(obj1, obj2, recursiveObjects) || PerformFieldByFieldComparision(obj1, obj2, recursiveObjects); } else { equals = obj1.Equals(obj2); } } else { LogFailedComparison("objects not viable for comparison", obj1.GetType(), obj1.GetType(), obj2.GetType()); equals = false; } } return(equals); }
private static bool PerformFieldByFieldComparision(object obj1, object obj2, ObjectReferenceDictionary recursiveObjects) { var equals = true; foreach (var currentField in obj1.GetAllFieldsWithoutAttribute <NoValueCompareAttribute>()) { var fieldValue1 = currentField.GetValue(obj1); var fieldValue2 = currentField.GetValue(obj2); IFieldValueEqualityComparer comparer; if (MatchesComparer(ref fieldValue1, ref fieldValue2, obj1, obj2, currentField, out comparer)) { equals = comparer.Equals(fieldValue1, fieldValue2); } else if (fieldValue1 as IDictionary != null) // Will not pass if null and can just use normal null checking { var dictionary1 = (IDictionary)fieldValue1; var dictionary2 = fieldValue2 as IDictionary; if (dictionary2 == null) { equals = false; } else { equals = AlreadyCompared(dictionary1, dictionary2, recursiveObjects) || (PerformListFieldComparison(dictionary1.Keys, dictionary2.Keys, recursiveObjects) && (PerformListFieldComparison(dictionary1.Values, dictionary2.Values, recursiveObjects))); } } else if (typeof(IEnumerable).IsAssignableFrom(currentField.FieldType) && typeof(string) != currentField.FieldType) // Will not pass if null and can just use normal null checking { equals = PerformListFieldComparison(fieldValue1 as IEnumerable, fieldValue2 as IEnumerable, recursiveObjects); } else if ((currentField.FieldType) == typeof(DateTime) || (currentField.FieldType) == typeof(DateTime?)) { equals = PerformDateTimeFieldComparison(fieldValue1, fieldValue2); } else if (ShouldFieldHaveValueSemanticEqualityPerformed(currentField)) { equals = PerformEntityFieldComparison(fieldValue1, fieldValue2, recursiveObjects); } else { equals = PerformBasicFieldComparison(fieldValue1, fieldValue2); } if (!equals) { LogFailedComparison(currentField.Name, obj1.GetType(), fieldValue1, fieldValue2); break; } } return(equals); }
private static bool AlreadyCompared(object target, object toCompare, ObjectReferenceDictionary recursiveObjects) { var alreadyCompared = false; if (recursiveObjects.ContainsKey(target)) { if (ReferenceEquals(recursiveObjects[target], toCompare)) { alreadyCompared = true; } } else { recursiveObjects.Add(target, toCompare); } return(alreadyCompared); }
private static bool CompareListElements(IEnumerable enumerable1, IEnumerable enumerable2, ObjectReferenceDictionary recursiveObjects, ref string failMessage) { var equal = true; var list1 = enumerable1 as IList <object> ?? enumerable1.Cast <object>().ToList(); var list2 = enumerable2 as IList <object> ?? enumerable2.Cast <object>().ToList(); if (list1.Count() != list2.Count()) { equal = false; failMessage = $"Expected length {list1.Count} but was {list2.Count}"; } else { var enumerator1 = list1.GetEnumerator(); var enumerator2 = list2.GetEnumerator(); var index = 0; while (enumerator1.MoveNext() && enumerator2.MoveNext()) { var instance1 = enumerator1.Current; var instance2 = enumerator2.Current; IFieldValueEqualityComparer comparer; if (instance1 == null) { equal = (instance2 == null); } else if (MatchesComparer(instance1, instance2, out comparer)) { equal = comparer.Equals(instance1, instance2); } else if (ShouldFieldHaveValueSemanticEqualityPerformed(instance1.GetType())) { equal = Compare(instance1, instance2, recursiveObjects); } else { equal = instance1.Equals(instance2); } if (!equal) { failMessage = $"Item's at index:{index} in the lists are not the same"; break; } index++; } } return(equal); }
private static bool PerformListFieldComparison(IEnumerable list1, IEnumerable list2, ObjectReferenceDictionary recursiveObjects, bool logOnFail = true) { bool equals; var failMessage = string.Empty; if ((list1 == null) || (list2 == null)) { equals = ((list1 == null) && (list2 == null)); } else if (ReferenceEquals(list1, list2)) { equals = true; } else { equals = CompareListElements(list1, list2, recursiveObjects, ref failMessage); } if (!equals && logOnFail) { var type = list1?.GetType() ?? list2.GetType(); LogFailedComparison(failMessage, type, list1, list2); } return(equals); }
private static bool PerformEntityFieldComparison(object value1, object value2, ObjectReferenceDictionary recursiveObjects) { bool equals; if ((value1 == null) || (value2 == null)) { equals = ((value1 == null) && (value2 == null)); } else { equals = Compare(value1, value2, recursiveObjects); } return(equals); }