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); } } }
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 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 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); } } }
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 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); } } } }
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"); } }
// 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); } }
/// <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)); }
/// <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))); }
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 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 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); }
internal static bool MemberValues <T>( T x, T y, MemberSettings settings, ReferencePairCollection referencePairs) { bool result; if (TryGetValueEquals(x, y, settings, out result)) { return(result); } referencePairs?.Add(x, y); if (x is IEnumerable) { if (!EnumerableEquals(x, y, settings, referencePairs)) { return(false); } } foreach (var member in settings.GetMembers(x.GetType())) { if (settings.IsIgnoringMember(member)) { continue; } var getterAndSetter = settings.GetOrCreateGetterAndSetter(member); bool equal; object yv; object xv; if (getterAndSetter.TryGetValueEquals(x, y, settings, out equal, out xv, out yv)) { if (!equal) { return(false); } continue; } if (member.MemberType().IsClass&& referencePairs?.Contains(xv, yv) == true) { continue; } if (!MemberValueEquals(xv, yv, member, settings, referencePairs)) { return(false); } } return(true); }
public CopyingComparer( IEqualityComparer <T> inner, MemberSettings settings, ReferencePairCollection referencePairs) { this.inner = inner; this.settings = settings; this.referencePairs = referencePairs; }
private static void Return(ReferencePairCollection pairs) { foreach (var pair in pairs.pairs) { pair.Dispose(); } pairs.pairs.Clear(); Cache.Enqueue(pairs); }
public void Copy( object source, object target, MemberSettings settings, ReferencePairCollection referencePairs) { var itemType = source.GetType().GetItemType(); var copyMethod = this.GetType() .GetMethod(nameof(Copy), BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(itemType); copyMethod.Invoke(null, new[] { source, target, settings, referencePairs }); }
/// <inheritdoc /> public override bool Equals( object x, object y, MemberSettings settings, ReferencePairCollection referencePairs) { if (TryGetEitherNullEquals(x, y, out var result)) { return(result); } return(Equals((Array)x, (Array)y, settings, referencePairs)); }
/// <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); }
internal static bool MemberValues <T>(T x, T y, MemberSettings settings) { if (TryGetValueEquals(x, y, settings, out var result)) { return(result); } Verify.CanEqualByMemberValues(x, y, settings, typeof(EqualBy).Name, settings.EqualByMethodName()); using (var borrowed = settings.ReferenceHandling == ReferenceHandling.Structural ? ReferencePairCollection.Borrow() : null) { return(MemberValues(x, y, settings, borrowed?.Value)); } }
/// <inheritdoc /> public override bool Equals( object x, object y, MemberSettings settings, ReferencePairCollection referencePairs) { bool result; if (TryGetEitherNullEquals(x, y, out result)) { return(result); } var xs = (ISet <T>)x; var ys = (ISet <T>)y; if (xs.Count != ys.Count) { return(false); } var isEquatable = settings.IsEquatable(x.GetType().GetItemType()); var xHashSet = xs as HashSet <T>; if (isEquatable) { if (Equals(xHashSet?.Comparer, EqualityComparer <T> .Default)) { return(xs.SetEquals(ys)); } return(this.ItemsEquals(xs, ys, EqualityComparer <T> .Default.Equals, EqualityComparer <T> .Default.GetHashCode)); } if (settings.ReferenceHandling == ReferenceHandling.References) { return(this.ItemsEquals(xs, ys, (xi, yi) => ReferenceEquals(xi, yi), xi => RuntimeHelpers.GetHashCode(xi))); } var hashCodeMethod = typeof(T).GetMethod(nameof(this.GetHashCode), new Type[0]); if (hashCodeMethod.DeclaringType == typeof(object)) { return(this.ItemsEquals(xs, ys, (xi, yi) => EqualBy.MemberValues(xi, yi, settings, referencePairs), _ => 0)); } return(this.ItemsEquals(xs, ys, (xi, yi) => EqualBy.MemberValues(xi, yi, settings, referencePairs), xi => xi.GetHashCode())); }
private static void Member <T>( T source, T target, MemberSettings settings, ReferencePairCollection referencePairs, MemberInfo member) { if (settings.IsIgnoringMember(member)) { return; } var getterAndSetter = settings.GetOrCreateGetterAndSetter(member); Member(source, target, settings, referencePairs, getterAndSetter); }
internal static void Copy <TKey, TValue>( IDictionary <TKey, TValue> source, IDictionary <TKey, TValue> target, MemberSettings settings, ReferencePairCollection referencePairs) { using (var toRemove = ListPool <TKey> .Borrow()) { foreach (var key in target.Keys) { if (!source.ContainsKey(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]; TValue tv; target.TryGetValue(key, out tv); 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); } } }
public void Copy( object source, object target, MemberSettings settings, ReferencePairCollection referencePairs) { var genericArguments = source.GetType() .GetInterface("IDictionary`2") .GetGenericArguments(); Debug.Assert(genericArguments.Length == 2, "genericArguments.Length != 2"); var copyMethod = this.GetType() .GetMethod(nameof(State.Copy), BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(genericArguments[0], genericArguments[1]); copyMethod.Invoke(null, new[] { source, target, settings, referencePairs }); }
private static void Copy( Array sourceArray, Array targetArray, MemberSettings settings, ReferencePairCollection referencePairs) { if (!Is.SameSize(sourceArray, targetArray)) { throw State.Copy.Throw.CannotCopyFixesSizeCollections(sourceArray, targetArray, settings); } var itemType = sourceArray.GetType().GetItemType(); var rank = sourceArray.Rank; if (rank < 4) { string methodName; switch (rank) { case 1: methodName = nameof(Copy1DItems); break; case 2: methodName = nameof(Copy2DItems); break; case 3: methodName = nameof(Copy3DItems); break; default: throw Throw.ShouldNeverGetHereException("Expected rank {1, 2, 3} was : " + rank); } var copyMethod = typeof(ArrayCopyer).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(itemType); copyMethod.Invoke(null, new object[] { sourceArray, targetArray, settings, referencePairs }); } else { CopyAnyDimension(sourceArray, targetArray, settings, referencePairs); } }
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); } } }
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); } } }
internal static void Member <T>( T source, T target, MemberSettings settings, MemberInfo member) where T : class { if (settings.IsIgnoringMember(member)) { return; } using (var borrowed = settings.ReferenceHandling == ReferenceHandling.Structural ? ReferencePairCollection.Borrow() : null) { Member(source, target, settings, borrowed?.Value, member); } }
internal static void Sync <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"); Verify.CanCopyMemberValues(source, target, settings); if (referencePairs?.Add(source, target) == false) { return; } if (TryCustomCopy(source, target, settings, out var copy)) { return; } CollectionItems(source, target, settings, referencePairs); Members(source, target, settings, referencePairs); }
private static void Copy <T>( IList <T> source, IList <T> target, MemberSettings settings, ReferencePairCollection referencePairs) { if (Is.IsFixedSize(source, target) && 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 void Member <T>( T source, T target, MemberSettings settings, ReferencePairCollection referencePairs, IGetterAndSetter getterAndSetter) { var sv = getterAndSetter.GetValue(source); var tv = getterAndSetter.GetValue(target); if (getterAndSetter.IsInitOnly) { if (settings.IsImmutable(getterAndSetter.ValueType) || sv == null) { return; } Sync(sv, tv, settings, referencePairs); return; } if (settings.IsImmutable(getterAndSetter.ValueType) || sv == null) { getterAndSetter.CopyValue(source, target); return; } bool created; bool needsSync; var clone = CloneWithoutSync(sv, tv, settings, out created, out needsSync); if (created) { getterAndSetter.SetValue(target, clone); } if (needsSync) { 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 bool Equals( IList <T> x, IList <T> y, MemberSettings settings, ReferencePairCollection referencePairs) { for (var i = 0; i < x.Count; i++) { var xv = x[i]; var yv = y[i]; if (referencePairs?.Contains(xv, yv) == true) { continue; } if (!EqualBy.MemberValues(xv, yv, settings, referencePairs)) { return(false); } } return(true); }
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)); }
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))); }