private static void CollectionItems( object source, object target, MemberSettings settings, ReferencePairCollection referencePairs) { if (!Is.Enumerable(source, target)) { return; } if (settings.ReferenceHandling == ReferenceHandling.Throw && !settings.IsImmutable(source.GetType().GetItemType())) { throw State.Throw.ShouldNeverGetHereException("Should have been checked for throw before copy"); } ICopyer copyer; if (ArrayCopyer.TryGetOrCreate(source, target, out copyer) || ListOfTCopyer.TryGetOrCreate(source, target, out copyer) || ListCopyer.TryGetOrCreate(source, target, out copyer) || DictionaryTKeyTValueCopyer.TryGetOrCreate(source, target, out copyer) || DictionaryCopyer.TryGetOrCreate(source, target, out copyer) || SetOfTCopyer.TryGetOrCreate(source, target, out copyer)) { copyer.Copy(source, target, settings, referencePairs); return; } if (source is IEnumerable || target is IEnumerable) { throw State.Throw.ShouldNeverGetHereException("Should be checked before"); } }
private static ErrorBuilder.TypeErrorsBuilder VerifyCore(MemberSettings settings, Type type) { return(ErrorBuilder.Start() .CheckRequiresReferenceHandling(type, settings, t => !settings.IsImmutable(t)) .CheckIsCopyableEnumerable(type, settings) .CheckIndexers(type, settings)); }
// ReSharper disable once UnusedParameter.Local private static bool MemberValueEquals( object x, object y, MemberInfo propertyInfo, MemberSettings settings, ReferencePairCollection referencePairs) { if (TryGetValueEquals(x, y, settings, out var result)) { return(result); } switch (settings.ReferenceHandling) { case ReferenceHandling.References: return(ReferenceEquals(x, y)); case ReferenceHandling.Structural: Verify.CanEqualByMemberValues(x, y, settings); return(MemberValues(x, y, settings, referencePairs)); case ReferenceHandling.Throw: throw Throw.ShouldNeverGetHereException(); default: throw new ArgumentOutOfRangeException( nameof(settings.ReferenceHandling), settings.ReferenceHandling, null); } }
private static TypeErrorsBuilder VerifyEnumerableRecursively( TypeErrorsBuilder typeErrors, Type type, MemberSettings settings, MemberPath memberPath, Func <MemberSettings, MemberPath, TypeErrors> getErrorsRecursively) { if (typeof(IEnumerable).IsAssignableFrom(type)) { memberPath = memberPath == null ? new MemberPath(type) : memberPath.WithCollectionItem(type); var recursiveErrors = getErrorsRecursively(settings, memberPath); if (recursiveErrors == null) { return(typeErrors); } var collectionErrors = new CollectionErrors(memberPath, recursiveErrors); typeErrors = typeErrors.CreateIfNull(type) .Add(collectionErrors); } return(typeErrors); }
internal static void CanEqualByMemberValues <T>( MemberSettings settings, string className, string methodName) { CanEqualByMemberValues(typeof(T), settings, className, methodName); }
private static TypeErrorsBuilder VerifyMemberRecursively( TypeErrorsBuilder typeErrors, Type type, MemberSettings settings, MemberPath memberPath, Func <MemberSettings, MemberPath, TypeErrors> getErrorsRecursively, MemberInfo memberInfo) { memberPath = memberPath.WithMember(memberInfo); if (memberPath.HasLoop()) { if (settings.ReferenceHandling == ReferenceHandling.Throw) { typeErrors = typeErrors.CreateIfNull(type) .Add(new ReferenceLoop(memberPath)); } return(typeErrors); } var recursiveErrors = getErrorsRecursively(settings, memberPath); if (recursiveErrors == null) { return(typeErrors); } var memberErrors = new MemberErrors(memberPath, recursiveErrors); typeErrors = typeErrors.CreateIfNull(type) .Add(memberErrors); return(typeErrors); }
private static void Copy1DItems <T>( T[] sourceArray, T[] targetArray, MemberSettings settings, ReferencePairCollection referencePairs) { var copyValues = State.Copy.IsCopyValue( sourceArray.GetType().GetItemType(), settings); for (var i = 0; i < sourceArray.Length; i++) { if (copyValues) { targetArray[i] = sourceArray[i]; continue; } var sv = sourceArray[i]; var tv = targetArray[i]; bool created; bool needsSync; var clone = State.Copy.CloneWithoutSync(sv, tv, settings, out created, out needsSync); if (created) { targetArray[i] = clone; } if (needsSync) { State.Copy.Sync(sv, clone, settings, referencePairs); } } }
public override bool Equals( object x, object y, MemberSettings settings, ReferencePairCollection referencePairs) { if (TryGetEitherNullEquals(x, y, out var result)) { return(result); } var xl = (IList <T>)x; var yl = (IList <T>)y; if (xl.Count != yl.Count) { return(false); } var isEquatable = settings.IsEquatable(typeof(T)); if (!typeof(T).IsValueType && settings.ReferenceHandling == ReferenceHandling.References) { return(isEquatable ? ItemsEquals(xl, yl, EqualityComparer <T> .Default.Equals) : ItemsEquals(xl, yl, (xi, yi) => ReferenceEquals(xi, yi))); } return(isEquatable ? ItemsEquals(xl, yl, EqualityComparer <T> .Default.Equals) : Equals(xl, yl, settings, referencePairs)); }
private static void ThrowIfHasErrors(this TypeErrors errors, MemberSettings settings, string className, string methodName) { if (errors == null) { return; } if (errors.Errors.Count == 1 && ReferenceEquals(errors.Errors[0], RequiresReferenceHandling.ComplexType)) { return; } var errorBuilder = new StringBuilder(); errorBuilder.AppendFailed(className, methodName) .AppendNotSupported(errors) .AppendSolveTheProblemBy() .AppendSuggestEquatable(errors) .AppendLine($"* Use {settings.GetType().Name} and specify how comparing is performed:") .AppendSuggestReferenceHandling(errors, settings) .AppendSuggestExclude(errors); var message = errorBuilder.ToString(); throw new NotSupportedException(message); }
private static void Members <T>(T source, T target, MemberSettings settings, ReferencePairCollection referencePairs) { Debug.Assert(source != null, nameof(source)); Debug.Assert(target != null, nameof(target)); Debug.Assert(source.GetType() == target.GetType(), "Must be same type"); using (var borrowed = ListPool <IGetterAndSetter> .Borrow()) { foreach (var member in settings.GetMembers(source.GetType())) { if (settings.IsIgnoringMember(member)) { continue; } var getterAndSetter = settings.GetOrCreateGetterAndSetter(member); Member(source, target, settings, referencePairs, getterAndSetter); if (getterAndSetter.IsInitOnly) { borrowed.Value.Add(getterAndSetter); } } foreach (var getterAndSetter in borrowed.Value) { var sv = getterAndSetter.GetValue(source); var tv = getterAndSetter.GetValue(target); if (!EqualBy.MemberValues(sv, tv, settings)) { Throw.ReadonlyMemberDiffers(new SourceAndTargetValue(source, sv, target, tv), getterAndSetter.Member, settings); } } } }
private static void TryAddCollectionDiffs( this DiffBuilder collectionBuilder, object x, object y, MemberSettings settings) { if (!Is.Enumerable(x, y)) { return; } if (ListDiffBy.TryGetOrCreate(x, y, out var comparer) || ReadonlyListDiffBy.TryGetOrCreate(x, y, out comparer) || ArrayDiffBy.TryGetOrCreate(x, y, out comparer) || DictionaryDiffBy.TryGetOrCreate(x, y, out comparer) || ReadOnlyDictionaryDiffBy.TryGetOrCreate(x, y, out comparer) || SetDiffBy.TryGetOrCreate(x, y, out comparer) || EnumerableDiffBy.TryGetOrCreate(x, y, out comparer)) { comparer.AddDiffs(collectionBuilder, x, y, settings); return; } throw Throw.ShouldNeverGetHereException("All enumarebles must be checked here"); }
private static void CollectionItems( object source, object target, MemberSettings settings, ReferencePairCollection referencePairs) { if (!Is.Enumerable(source, target)) { return; } if (settings.ReferenceHandling == ReferenceHandling.Throw && !settings.IsImmutable(source.GetType().GetItemType())) { throw State.Throw.ShouldNeverGetHereException("Should have been checked for throw before copy"); } if (ArrayCopyer.TryGetOrCreate(source, target, out var copyer) || ListOfTCopyer.TryGetOrCreate(source, target, out copyer) || ListCopyer.TryGetOrCreate(source, target, out copyer) || DictionaryTKeyTValueCopyer.TryGetOrCreate(source, target, out copyer) || DictionaryCopyer.TryGetOrCreate(source, target, out copyer) || SetOfTCopyer.TryGetOrCreate(source, target, out copyer)) { copyer.Copy(source, target, settings, referencePairs); return; } if (source is IEnumerable || target is IEnumerable) { throw State.Throw.ShouldNeverGetHereException("Should be checked before"); } }
/// <inheritdoc /> public override bool Equals( object x, object y, MemberSettings settings, ReferencePairCollection referencePairs) { bool result; if (TryGetEitherNullEquals(x, y, out result)) { return(result); } var xd = (IReadOnlyDictionary <TKey, TValue>)x; var yd = (IReadOnlyDictionary <TKey, TValue>)y; if (xd.Count != yd.Count) { return(false); } if (settings.IsEquatable(typeof(TValue))) { return(KeysAndValuesEquals(xd, yd, EqualityComparer <TValue> .Default.Equals)); } if (settings.ReferenceHandling == ReferenceHandling.References) { return(KeysAndValuesEquals(xd, yd, (xi, yi) => ReferenceEquals(xi, yi))); } return(KeysAndValuesEquals(xd, yd, settings, referencePairs)); }
internal static bool KeysAndValuesEquals( IReadOnlyDictionary <TKey, TValue> x, IReadOnlyDictionary <TKey, TValue> y, MemberSettings settings, ReferencePairCollection referencePairs) { foreach (var key in x.Keys) { var xv = x[key]; TValue yv; if (!y.TryGetValue(key, out yv)) { return(false); } if (referencePairs?.Contains(xv, yv) == true) { continue; } if (!EqualBy.MemberValues(xv, yv, settings, referencePairs)) { return(false); } } return(true); }
private static void Copy2DItems <T>( T[,] sourceArray, T[,] targetArray, MemberSettings settings, ReferencePairCollection referencePairs) { var copyValues = State.Copy.IsCopyValue( sourceArray.GetType().GetItemType(), settings); for (var i = sourceArray.GetLowerBound(0); i <= sourceArray.GetUpperBound(0); i++) { for (var j = sourceArray.GetLowerBound(1); j <= sourceArray.GetUpperBound(1); j++) { if (copyValues) { targetArray[i, j] = sourceArray[i, j]; continue; } var sv = sourceArray[i, j]; var tv = targetArray[i, j]; var clone = State.Copy.CloneWithoutSync(sv, tv, settings, out var created, out var needsSync); if (created) { targetArray[i, j] = clone; } if (needsSync) { State.Copy.Sync(sv, clone, settings, referencePairs); } } } }
internal static TypeErrorsBuilder VerifyRecursive( this TypeErrorsBuilder typeErrors, Type type, MemberSettings settings, MemberPath memberPath, Func <MemberSettings, MemberPath, TypeErrors> getPropertyErrors) { if (settings.ReferenceHandling == ReferenceHandling.References) { return(typeErrors); } typeErrors = VerifyEnumerableRecursively(typeErrors, type, settings, memberPath, getPropertyErrors); foreach (var member in settings.GetMembers(type)) { if (settings.IsIgnoringMember(member)) { continue; } if (memberPath == null) { memberPath = new MemberPath(type); } typeErrors = VerifyMemberRecursively(typeErrors, type, settings, memberPath, getPropertyErrors, member); } return(typeErrors); }
private static void CopyAnyDimension( Array sourceArray, Array targetArray, MemberSettings settings, ReferencePairCollection referencePairs) { var copyValues = State.Copy.IsCopyValue( sourceArray.GetType().GetItemType(), settings); foreach (var index in sourceArray.Indices()) { if (copyValues) { targetArray.SetValue(sourceArray.GetValue(index), index); continue; } var sv = sourceArray.GetValue(index); var tv = targetArray.GetValue(index); bool created; bool needsSync; var clone = State.Copy.CloneWithoutSync(sv, tv, settings, out created, out needsSync); if (created) { targetArray.SetValue(clone, index); } if (needsSync) { State.Copy.Sync(sv, clone, settings, referencePairs); } } }
internal static bool TryGetValueEquals <T>(T x, T y, MemberSettings settings, out bool result) { if (ReferenceEquals(x, y)) { result = true; return(true); } if (x == null || y == null) { result = false; return(true); } if (x.GetType() != y.GetType()) { result = false; return(true); } if (settings.TryGetComparer(x.GetType(), out var comparer)) { result = comparer.Equals(x, y); return(true); } if (settings.IsEquatable(x.GetType())) { result = Equals(x, y); return(true); } result = false; return(false); }
internal static object CreateInstance(object sourceValue, MemberSettings settings) { if (sourceValue == null) { return(null); } var type = sourceValue.GetType(); if (type.IsArray) { var constructor = type.GetConstructor(new[] { typeof(int) }); var parameters = new[] { type.GetProperty("Length").GetValue(sourceValue) }; //// ReSharper disable once PossibleNullReferenceException nope, never null here var array = constructor.Invoke(parameters); return(array); } if (settings.IsImmutable(type)) { return(sourceValue); } try { return(Activator.CreateInstance(type, true)); } catch (Exception e) { throw Throw.CreateCannotCreateInstanceException(sourceValue, settings, e); } }
internal static bool TryCreate(object x, object y, MemberSettings settings, out IRefCounted <DiffBuilder> subDiffBuilder) { bool created; subDiffBuilder = TrackerCache.GetOrAdd(x, y, settings, pair => new DiffBuilder(pair, settings), out created); return(created); }
/// <inheritdoc /> public override bool Equals( object x, object y, MemberSettings settings, ReferencePairCollection referencePairs) { bool result; if (TryGetEitherNullEquals(x, y, out result)) { return(result); } var isEquatable = settings.IsEquatable(typeof(T)); if (settings.ReferenceHandling == ReferenceHandling.References) { return(isEquatable ? ItemsEquals((IEnumerable <T>)x, (IEnumerable <T>)y, EqualityComparer <T> .Default.Equals) : ItemsEquals((IEnumerable <T>)x, (IEnumerable <T>)y, (xi, yi) => ReferenceEquals(xi, yi))); } return(isEquatable ? ItemsEquals((IEnumerable <T>)x, (IEnumerable <T>)y, EqualityComparer <T> .Default.Equals) : ItemsEquals((IEnumerable <T>)x, (IEnumerable <T>)y, (xi, yi) => EqualBy.MemberValues(xi, yi, settings, referencePairs))); }
private static void Copy <T>( ISet <T> source, ISet <T> target, MemberSettings settings, ReferencePairCollection referencePairs) { if (Is.IsFixedSize(source, target) && source.Count != target.Count) { throw State.Copy.Throw.CannotCopyFixesSizeCollections(source, target, settings); } if (settings.IsImmutable(typeof(T))) { using (var borrow = HashSetPool <T> .Borrow(EqualityComparer <T> .Default)) { borrow.Value.UnionWith(source); target.IntersectWith(borrow.Value); target.UnionWith(borrow.Value); return; } } switch (settings.ReferenceHandling) { case ReferenceHandling.Throw: break; case ReferenceHandling.References: using (var borrow = HashSetPool <T> .Borrow((x, y) => ReferenceEquals(x, y), x => RuntimeHelpers.GetHashCode(x))) { borrow.Value.UnionWith(source); target.IntersectWith(borrow.Value); target.UnionWith(borrow.Value); } break; case ReferenceHandling.Structural: IEqualityComparer <T> comparer; if (!Set.TryGetComparer(source, out comparer)) { comparer = EqualityComparer <T> .Default; } var copyIngComparer = new CopyingComparer <T>(comparer, settings, referencePairs); using (var borrow = HashSetPool <T> .Borrow(copyIngComparer)) { borrow.Value.UnionWith(source); target.IntersectWith(borrow.Value); copyIngComparer.StartCopying(); target.UnionWith(borrow.Value); } return; default: throw new ArgumentOutOfRangeException(); } }
public void AddDiffs( DiffBuilder collectionBuilder, object x, object y, MemberSettings settings) { this.AddDiffs(collectionBuilder, (IReadOnlyList <T>)x, (IReadOnlyList <T>)y, settings); }
public void AddDiffs( DiffBuilder collectionBuilder, object x, object y, MemberSettings settings) { this.AddDiffs(collectionBuilder, (IDictionary <TKey, TValue>)x, (IDictionary <TKey, TValue>)y, settings); }
public void AddDiffs( DiffBuilder collectionBuilder, object x, object y, MemberSettings settings) { this.AddDiffs(collectionBuilder, (Array)x, (Array)y, settings); }
public void AddDiffs( DiffBuilder collectionBuilder, object x, object y, MemberSettings settings) { this.AddDiffs(collectionBuilder, (IEnumerable <T>)x, (IEnumerable <T>)y, settings); }
public void Copy( object source, object target, MemberSettings settings, ReferencePairCollection referencePairs) { Copy((IDictionary)source, (IDictionary)target, settings, referencePairs); }
public void Copy( object source, object target, MemberSettings settings, ReferencePairCollection referencePairs) { Copy((Array)source, (Array)target, settings, referencePairs); }
// ReSharper disable once UnusedParameter.Local internal static void IfHasErrors(TypeErrors errors, MemberSettings settings, string className, string methodName) { if (errors.HasErrors()) { var message = GetErrorText(errors, settings, className, methodName); throw new NotSupportedException(message); } }
public bool TryGetValueEquals(object x, object y, MemberSettings settings, out bool equal, out object xv, out object yv) { var result = this.TryGetValueEquals((TSource)x, (TSource)y, settings, out equal, out var xValue, out var yValue); xv = xValue; yv = yValue; return(result); }
internal static bool IsCopyValue(Type type, MemberSettings settings) { if (settings.IsImmutable(type) || settings.ReferenceHandling == ReferenceHandling.References) { return(true); } return(false); }
public CopyingComparer( IEqualityComparer <T> inner, MemberSettings settings, ReferencePairCollection referencePairs) { this.inner = inner; this.settings = settings; this.referencePairs = referencePairs; }
// ReSharper disable once UnusedParameter.Local internal static Exception CannotCopyFixesSizeCollections( IEnumerable source, IEnumerable target, MemberSettings settings) { var error = new CannotCopyFixedSizeCollectionsError(source, target); var typeErrors = new TypeErrors(target.GetType(), error); var message = typeErrors.GetErrorText(settings, typeof(Copy).Name, settings.CopyMethodName()); return new InvalidOperationException(message); }
// ReSharper disable once UnusedParameter.Local internal static void ReadonlyMemberDiffers( SourceAndTargetValue sourceAndTargetValue, MemberInfo member, MemberSettings settings) { var error = new ReadonlyMemberDiffersError(sourceAndTargetValue, member); var typeErrors = new TypeErrors(sourceAndTargetValue.Source?.GetType(), error); var message = typeErrors.GetErrorText(settings, typeof(Copy).Name, settings.CopyMethodName()); throw new InvalidOperationException(message); }
/// <inheritdoc /> public override bool Equals( object x, object y, MemberSettings settings, ReferencePairCollection referencePairs) { bool result; if (TryGetEitherNullEquals(x, y, out result)) { return result; } return Equals((Array)x, (Array)y, settings, referencePairs); }
// ReSharper disable once UnusedParameter.Local private static void ThrowIfHasErrors(this TypeErrors errors, MemberSettings settings, string className, string methodName) { if (errors == null) { return; } if (errors.Errors.Count == 1 && ReferenceEquals(errors.Errors[0], RequiresReferenceHandling.ComplexType)) { return; } var message = errors.GetErrorText(settings, className, methodName); throw new NotSupportedException(message); }
internal static TypeErrorsBuilder CheckRequiresReferenceHandling( this TypeErrorsBuilder typeErrors, Type type, MemberSettings settings, Func<Type, bool> requiresReferenceHandling) { if (settings.ReferenceHandling == ReferenceHandling.Throw) { if (typeof(IEnumerable).IsAssignableFrom(type)) { if (type.Implements(typeof(IDictionary<,>))) { var arguments = type.GetGenericArguments(); if (arguments.Length != 2 || requiresReferenceHandling(arguments[0]) || requiresReferenceHandling(arguments[1])) { typeErrors = typeErrors.CreateIfNull(type) .Add(RequiresReferenceHandling.Enumerable); } } else if (requiresReferenceHandling(type.GetItemType())) { typeErrors = typeErrors.CreateIfNull(type) .Add(RequiresReferenceHandling.Enumerable); } } else if (type.IsKeyValuePair()) { var arguments = type.GetGenericArguments(); if (requiresReferenceHandling(arguments[0]) || requiresReferenceHandling(arguments[1])) { typeErrors = typeErrors.CreateIfNull(type) .Add(RequiresReferenceHandling.ComplexType); } } else if (requiresReferenceHandling(type)) { typeErrors = typeErrors.CreateIfNull(type) .Add(RequiresReferenceHandling.ComplexType); } } return typeErrors; }
private void AddDiffs( DiffBuilder collectionBuilder, Array x, Array y, MemberSettings settings) { RankDiff rankDiff; if (TryGetRankDiff(x, y, out rankDiff)) { collectionBuilder.Add(rankDiff); return; } foreach (var index in x.Indices()) { collectionBuilder.UpdateCollectionItemDiff(x.GetValue(index), y.GetValue(index), new Index(index), settings); } }
// ReSharper disable once UnusedParameter.Local private static string GetErrorText(this TypeErrors errors, MemberSettings settings, string className, string methodName) { var errorBuilder = new StringBuilder(); errorBuilder.AppendCopyFailed(className, methodName) .AppendNotSupported(errors) .AppendSolveTheProblemBy() .AppendSuggestImmutable(errors) .AppendSuggestResizableCollection(errors) .AppendSuggestDefaultCtor(errors) .AppendLine($"* Use {settings.GetType().Name} and specify how copying is performed:") .AppendLine($" - {typeof(ReferenceHandling).Name}.{nameof(ReferenceHandling.Structural)} means that a the entire graph is traversed and immutable property values are copied.") .AppendLine($" - For structural Activator.CreateInstance is used to create instances so a parameterless constructor may be needed, can be private.") .AppendLine($" - {typeof(ReferenceHandling).Name}.{nameof(ReferenceHandling.References)} means that references are copied.") .AppendSuggestExclude(errors); var message = errorBuilder.ToString(); return message; }
internal static void Copy( IDictionary source, IDictionary target, MemberSettings settings, ReferencePairCollection referencePairs) { using (var toRemove = ListPool<object>.Borrow()) { foreach (var key in target.Keys) { if (!source.Contains(key)) { toRemove.Value.Add(key); } else { // Synchronize key? } } foreach (var key in toRemove.Value) { target.Remove(key); } } foreach (var key in source.Keys) { var sv = source[key]; var tv = target.ElementAtOrDefault(key); bool created; bool needsSync; var clone = State.Copy.CloneWithoutSync(sv, tv, settings, out created, out needsSync); if (created) { target[key] = clone; } if (needsSync) { State.Copy.Sync(sv, clone, settings, referencePairs); } } }
private static void Copy( IList source, IList target, MemberSettings settings, ReferencePairCollection referencePairs) { if ((source.IsFixedSize || target.IsFixedSize) && source.Count != target.Count) { throw State.Copy.Throw.CannotCopyFixesSizeCollections(source, target, settings); } var copyValues = State.Copy.IsCopyValue( source.GetType().GetItemType(), settings); for (var i = 0; i < source.Count; i++) { if (copyValues) { target.SetElementAt(i, source[i]); continue; } var sv = source[i]; var tv = target.ElementAtOrDefault(i); bool created; bool needsSync; var clone = State.Copy.CloneWithoutSync(sv, tv, settings, out created, out needsSync); if (created) { target.SetElementAt(i, clone); } if (needsSync) { State.Copy.Sync(sv, clone, settings, referencePairs); } } target.TrimLengthTo(source); }
private static StringBuilder AppendSuggestReferenceHandling( this StringBuilder errorBuilder, TypeErrors errors, MemberSettings settings) { var references = $" - {typeof(ReferenceHandling).Name}.{nameof(ReferenceHandling.References)} means that reference equality is used."; if (settings.ReferenceHandling == ReferenceHandling.Throw) { if (errors.AllErrors.OfType<RequiresReferenceHandling>().Any()) { return errorBuilder.AppendLine($" - {typeof(ReferenceHandling).Name}.{nameof(ReferenceHandling.Structural)} means that a deep equals is performed.") .AppendLine(references); } } if (errors.AllErrors.OfType<ReferenceLoop>().Any()) { return errorBuilder.AppendLine(references); } return errorBuilder; }
private static bool Equals( Array x, Array y, MemberSettings settings, ReferencePairCollection referencePairs) { if (!Is.SameSize(x, y)) { return false; } var isEquatable = settings.IsEquatable(x.GetType().GetItemType()); if (settings.ReferenceHandling == ReferenceHandling.References) { return isEquatable ? ItemsEquals(x, y, Equals) : ItemsEquals(x, y, ReferenceEquals); } return isEquatable ? ItemsEquals(x, y, Equals) : ItemsEquals(x, y, (xi, yi) => EqualBy.MemberValues(xi, yi, settings, referencePairs)); }
internal static TypeErrorsBuilder CheckIndexers(this TypeErrorsBuilder typeErrors, Type type, MemberSettings settings) { var propertiesSettings = settings as PropertiesSettings; var propertyInfos = type.GetProperties(settings.BindingFlags); foreach (var propertyInfo in propertyInfos) { if (propertyInfo.GetIndexParameters().Length == 0) { continue; } if (propertiesSettings?.IsIgnoringProperty(propertyInfo) == true) { continue; } if (settings.IsIgnoringDeclaringType(propertyInfo.DeclaringType)) { continue; } typeErrors = typeErrors.CreateIfNull(type) .Add(UnsupportedIndexer.GetOrCreate(propertyInfo)); } return typeErrors; }
private static TypeErrorsBuilder VerifyMemberRecursively( TypeErrorsBuilder typeErrors, Type type, MemberSettings settings, MemberPath memberPath, Func<MemberSettings, MemberPath, TypeErrors> getErrorsRecursively, MemberInfo memberInfo) { memberPath = memberPath.WithMember(memberInfo); if (memberPath.HasLoop()) { if (settings.ReferenceHandling == ReferenceHandling.Throw) { typeErrors = typeErrors.CreateIfNull(type) .Add(new ReferenceLoop(memberPath)); } return typeErrors; } var recursiveErrors = getErrorsRecursively(settings, memberPath); if (recursiveErrors == null) { return typeErrors; } var memberErrors = new MemberErrors(memberPath, recursiveErrors); typeErrors = typeErrors.CreateIfNull(type) .Add(memberErrors); return typeErrors; }
private static TypeErrorsBuilder VerifyEnumerableRecursively( TypeErrorsBuilder typeErrors, Type type, MemberSettings settings, MemberPath memberPath, Func<MemberSettings, MemberPath, TypeErrors> getErrorsRecursively) { if (typeof(IEnumerable).IsAssignableFrom(type)) { memberPath = memberPath == null ? new MemberPath(type) : memberPath.WithCollectionItem(type); var recursiveErrors = getErrorsRecursively(settings, memberPath); if (recursiveErrors == null) { return typeErrors; } var collectionErrors = new CollectionErrors(memberPath, recursiveErrors); typeErrors = typeErrors.CreateIfNull(type) .Add(collectionErrors); } return typeErrors; }
internal static TypeErrorsBuilder VerifyRecursive( this TypeErrorsBuilder typeErrors, Type type, MemberSettings settings, MemberPath memberPath, Func<MemberSettings, MemberPath, TypeErrors> getPropertyErrors) { if (settings.ReferenceHandling == ReferenceHandling.References) { return typeErrors; } typeErrors = VerifyEnumerableRecursively(typeErrors, type, settings, memberPath, getPropertyErrors); foreach (var member in settings.GetMembers(type)) { if (settings.IsIgnoringMember(member)) { continue; } if (memberPath == null) { memberPath = new MemberPath(type); } typeErrors = VerifyMemberRecursively(typeErrors, type, settings, memberPath, getPropertyErrors, member); } return typeErrors; }
internal static TypeErrorsBuilder CheckNotifies(this TypeErrorsBuilder typeErrors, Type type, MemberSettings settings) { if (settings.IsImmutable(type)) { return typeErrors; } if (type.IsValueType) { if (typeof(INotifyCollectionChanged).IsAssignableFrom(type) || typeof(INotifyPropertyChanged).IsAssignableFrom(type)) { return typeErrors.CreateIfNull(type) .Add(StructMustNotNotifyError.GetOrCreate(type)); } return typeErrors; } if (typeof(IEnumerable).IsAssignableFrom(type)) { if (!typeof(INotifyCollectionChanged).IsAssignableFrom(type)) { return typeErrors.CreateIfNull(type) .Add(CollectionMustNotifyError.GetOrCreate(type)); } } else if (!typeof(INotifyPropertyChanged).IsAssignableFrom(type)) { if (settings.IsIgnoringDeclaringType(type)) { return typeErrors; } return typeErrors.CreateIfNull(type) .Add(TypeMustNotifyError.GetOrCreate(type)); } return typeErrors; }
internal static InvalidOperationException CreateCannotCreateInstanceException( object sourceValue, MemberSettings settings, Exception exception) { var cannotCopyError = new CannotCreateInstanceError(sourceValue); var typeErrors = new TypeErrors(sourceValue.GetType(), new Error[] { cannotCopyError }); var message = typeErrors.GetErrorText(settings, typeof(Copy).Name, settings.CopyMethodName()); return new InvalidOperationException(message, exception); }