public override IEnumerable <Difference> CalculateDifferences(Type type, object obj1, object obj2) { if (!type.InheritsFrom(typeof(HashSet <>))) { throw new ArgumentException("Invalid type"); } if (!Settings.EmptyAndNullEnumerablesEqual && (obj1 == null || obj2 == null) && obj1 != obj2) { yield break; } obj1 = obj1 ?? new HashSet <T>(); obj2 = obj2 ?? new HashSet <T>(); if (!obj1.GetType().InheritsFrom(typeof(HashSet <T>))) { throw new ArgumentException(nameof(obj1)); } if (!obj2.GetType().InheritsFrom(typeof(HashSet <T>))) { throw new ArgumentException(nameof(obj2)); } var hashSet1 = ((IEnumerable <T>)obj1).ToList(); var hashSet2 = ((IEnumerable <T>)obj2).ToList(); var valueComparer = OverridesCollection.GetComparer(typeof(T)) ?? DefaultValueComparer; foreach (var element in hashSet1) { if (!hashSet2.Contains(element)) { yield return(new Difference("", valueComparer.ToString(element), string.Empty, DifferenceTypes.MissedElementInSecondObject)); } } foreach (var element in hashSet2) { if (!hashSet1.Contains(element)) { yield return(new Difference("", string.Empty, valueComparer.ToString(element), DifferenceTypes.MissedElementInFirstObject)); } } }
public override IEnumerable<Difference> CalculateDifferences(Type type, object obj1, object obj2) { if (!Settings.EmptyAndNullEnumerablesEqual && (obj1 == null || obj2 == null) && obj1 != obj2) { yield return new Difference("[]", obj1?.ToString() ?? string.Empty, obj2?.ToString() ?? string.Empty); yield break; } obj1 = obj1 ?? Enumerable.Empty<object>(); obj2 = obj2 ?? Enumerable.Empty<object>(); if (!type.InheritsFrom(typeof(IEnumerable))) { throw new ArgumentException(nameof(type)); } if (!obj1.GetType().InheritsFrom(typeof(IEnumerable))) { throw new ArgumentException(nameof(obj1)); } if (!obj2.GetType().InheritsFrom(typeof(IEnumerable))) { throw new ArgumentException(nameof(obj2)); } var array1 = ((IEnumerable)obj1).Cast<object>().ToArray(); var array2 = ((IEnumerable)obj2).Cast<object>().ToArray(); if (array1.Length != array2.Length) { yield return new Difference("", array1.Length.ToString(), array2.Length.ToString(), DifferenceTypes.NumberOfElementsMismatch); yield break; } //ToDo Extract type for (var i = 0; i < array2.Length; i++) { if (array1[i] == null && array2[i] == null) { continue; } var valueComparer1 = array1[i] != null ? OverridesCollection.GetComparer(array1[i].GetType()) ?? DefaultValueComparer : DefaultValueComparer; var valueComparer2 = array2[i] != null ? OverridesCollection.GetComparer(array2[i].GetType()) ?? DefaultValueComparer : DefaultValueComparer; if (array1[i] == null) { yield return new Difference($"[{i}]", string.Empty, valueComparer2.ToString(array2[i])); continue; } if (array2[i] == null) { yield return new Difference($"[{i}]", valueComparer1.ToString(array1[i]), string.Empty); continue; } if (array1[i].GetType() != array2[i].GetType()) { yield return new Difference($"[{i}]", valueComparer1.ToString(array1[i]), valueComparer2.ToString(array2[i]), DifferenceTypes.TypeMismatch); continue; } var comparer = Factory.GetObjectsComparer(array1[i].GetType(), Settings, this); foreach (var failure in comparer.CalculateDifferences(array1[i].GetType(), array1[i], array2[i])) { yield return failure.InsertPath($"[{i}]"); } } }
public override IEnumerable <Difference> CalculateDifferences(Type type, object obj1, object obj2) { var castedObject1 = (T)obj1; var castedObject2 = (T)obj2; var propertyKeys1 = GetProperties(castedObject1); var propertyKeys2 = GetProperties(castedObject2); var propertyKeys = propertyKeys1.Union(propertyKeys2); foreach (var propertyKey in propertyKeys) { var existsInObject1 = propertyKeys1.Contains(propertyKey); var existsInObject2 = propertyKeys2.Contains(propertyKey); object value1 = null; if (existsInObject1) { TryGetMemberValue(castedObject1, propertyKey, out value1); } object value2 = null; if (existsInObject2) { TryGetMemberValue(castedObject2, propertyKey, out value2); } var propertyType = (value1 ?? value2)?.GetType() ?? typeof(object); var customComparer = OverridesCollection.GetComparer(propertyType) ?? OverridesCollection.GetComparer(propertyKey); var valueComparer = customComparer ?? DefaultValueComparer; if (Settings.UseDefaultIfMemberNotExist) { if (!existsInObject1) { value1 = propertyType.GetDefaultValue(); } if (!existsInObject2) { value2 = propertyType.GetDefaultValue(); } } if (!Settings.UseDefaultIfMemberNotExist) { if (!existsInObject1) { yield return(new Difference(propertyKey, string.Empty, valueComparer.ToString(value2), DifferenceTypes.MissedMemberInFirstObject)); continue; } if (!existsInObject2) { yield return(new Difference(propertyKey, valueComparer.ToString(value1), string.Empty, DifferenceTypes.MissedMemberInSecondObject)); continue; } } if (value1 != null && value2 != null && value1.GetType() != value2.GetType()) { var valueComparer2 = OverridesCollection.GetComparer(value2.GetType()) ?? OverridesCollection.GetComparer(propertyKey) ?? DefaultValueComparer; yield return(new Difference(propertyKey, valueComparer.ToString(value1), valueComparer2.ToString(value2), DifferenceTypes.TypeMismatch)); continue; } //null cannot be casted to ValueType if (value1 == null && value2 != null && value2.GetType().GetTypeInfo().IsValueType || value2 == null && value1 != null && value1.GetType().GetTypeInfo().IsValueType) { var valueComparer2 = value2 != null? OverridesCollection.GetComparer(value2.GetType()) ?? OverridesCollection.GetComparer(propertyKey) ?? DefaultValueComparer: DefaultValueComparer; yield return(new Difference(propertyKey, valueComparer.ToString(value1), valueComparer2.ToString(value2), DifferenceTypes.TypeMismatch)); continue; } if (customComparer != null) { if (!customComparer.Compare(value1, value2, Settings)) { yield return(new Difference(propertyKey, customComparer.ToString(value1), customComparer.ToString(value2))); } continue; } var comparer = Factory.GetObjectsComparer(propertyType, Settings, this); foreach (var failure in comparer.CalculateDifferences(propertyType, value1, value2)) { yield return(failure.InsertPath(propertyKey)); } } }
internal IEnumerable <Difference> CalculateDifferences(T obj1, T obj2, MemberInfo memberInfo) { var comparer = memberInfo != null ? OverridesCollection.GetComparer(memberInfo) : OverridesCollection.GetComparer(typeof(T)); if (typeof(T).IsComparable() || comparer != null) { comparer = comparer ?? DefaultValueComparer; if (!comparer.Compare(obj1, obj2, Settings)) { yield return (new Difference(string.Empty, comparer.ToString(obj1), comparer.ToString(obj2))); } yield break; } var conditionalComparer = _conditionalComparers.FirstOrDefault(c => c.IsMatch(typeof(T), obj1, obj2)); if (conditionalComparer != null) { foreach (var difference in conditionalComparer.CalculateDifferences(typeof(T), obj1, obj2)) { yield return(difference); } if (conditionalComparer.IsStopComparison(typeof(T), obj1, obj2)) { yield break; } } if (obj1 == null || obj2 == null) { if (!DefaultValueComparer.Compare(obj1, obj2, Settings)) { yield return(new Difference(string.Empty, DefaultValueComparer.ToString(obj1), DefaultValueComparer.ToString(obj2))); } yield break; } if (!Settings.RecursiveComparison) { yield break; } foreach (var member in _members) { var value1 = member.GetMemberValue(obj1); var value2 = member.GetMemberValue(obj2); var type = member.GetMemberType(); if (conditionalComparer != null && conditionalComparer.SkipMember(typeof(T), member)) { continue; } var valueComparer = DefaultValueComparer; var hasCustomComparer = false; var comparerOverride = OverridesCollection.GetComparer(member); if (comparerOverride != null) { valueComparer = comparerOverride; hasCustomComparer = true; } if (!hasCustomComparer && !type.IsComparable()) { var objectDataComparer = Factory.GetObjectsComparer(type, Settings, this); foreach (var failure in objectDataComparer.CalculateDifferences(type, value1, value2)) { yield return(failure.InsertPath(member.Name)); } continue; } if (!valueComparer.Compare(value1, value2, Settings)) { yield return(new Difference(member.Name, valueComparer.ToString(value1), valueComparer.ToString(value2))); } } }