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"); }
public void AddDiffs( DiffBuilder collectionBuilder, object x, object y, MemberSettings settings) { this.AddDiffs(collectionBuilder, (IEnumerable <T>)x, (IEnumerable <T>)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, (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); }
internal void AddLazy(object index, DiffBuilder builder) { Debug.Assert(!this.disposed, "this.disposed"); lock (this.gate) { this.needsRefresh = true; this.KeyedDiffs[index] = new IndexDiff(index, builder.valueDiff); this.UpdateSubBuilder(index, builder); } }
internal void AddLazy(MemberInfo member, DiffBuilder builder) { Debug.Assert(!this.disposed, "this.disposed"); lock (this.gate) { this.needsRefresh = true; this.KeyedDiffs[member] = MemberDiff.Create(member, builder.valueDiff); this.UpdateSubBuilder(member, builder); } }
internal static void UpdateDiffs <T>( this DiffBuilder builder, T x, T y, MemberSettings settings) { EqualBy.Verify.CanEqualByMemberValues(x, y, settings, typeof(DiffBy).Name, settings.DiffMethodName()); builder.TryAddCollectionDiffs(x, y, settings); TryAddMemberDiffs(x, y, settings, builder); }
private static void TryAddMemberDiffs( object x, object y, MemberSettings settings, DiffBuilder builder) { foreach (var member in settings.GetMembers(x.GetType())) { builder.UpdateMemberDiff(x, y, member, settings); } }
private void AddDiffs( DiffBuilder collectionBuilder, IReadOnlyList <T> x, IReadOnlyList <T> y, MemberSettings settings) { for (var i = 0; i < Math.Max(x.Count, y.Count); i++) { var xv = x.ElementAtOrMissing(i); var yv = y.ElementAtOrMissing(i); collectionBuilder.UpdateCollectionItemDiff(xv, yv, i, settings); } }
private void AddDiffs( DiffBuilder collectionBuilder, IEnumerable <T> x, IEnumerable <T> y, MemberSettings settings) { var i = -1; foreach (var pair in new PaddedPairs(x, y)) { i++; collectionBuilder.UpdateCollectionItemDiff(pair.X, pair.Y, new Skip(i), settings); } }
private void UpdateSubBuilder(object key, DiffBuilder builder) { if (builder == null) { this.KeyedSubBuilders.TryRemoveAndDispose(key); return; } if (!builder.TryRefCount(out var refCounted, out var created)) { throw Throw.ShouldNeverGetHereException("UpdateSubBuilder failed, try refcount failed"); } this.KeyedSubBuilders.AddOrUpdate(key, refCounted); }
internal static void UpdateCollectionItemDiff( this DiffBuilder collectionBuilder, object xItem, object yItem, object index, MemberSettings settings) { ValueDiff diff; if (TryGetValueDiff(xItem, yItem, settings, out diff)) { if (diff != null) { collectionBuilder.Add(new IndexDiff(index, diff)); } else { collectionBuilder.Remove(index); } return; } if (settings.ReferenceHandling == ReferenceHandling.References) { if (ReferenceEquals(xItem, yItem)) { collectionBuilder.Remove(index); } else { collectionBuilder.Add(new IndexDiff(index, new ValueDiff(xItem, yItem))); } return; } IRefCounted <DiffBuilder> subDiffBuilder; if (DiffBuilder.TryCreate(xItem, yItem, settings, out subDiffBuilder)) { subDiffBuilder.Value.UpdateDiffs(xItem, yItem, settings); } collectionBuilder.AddLazy(index, subDiffBuilder.Value); }
private void AddDiffs( DiffBuilder collectionBuilder, Array x, Array y, MemberSettings settings) { if (TryGetRankDiff(x, y, out var rankDiff)) { collectionBuilder.Add(rankDiff); return; } foreach (var index in x.Indices()) { collectionBuilder.UpdateCollectionItemDiff(x.GetValue(index), y.GetValue(index), new Index(index), settings); } }
private static ValueDiff TryCreateValueDiff <T>(T x, T y, MemberSettings settings) { Debug.Assert(x != null, "x == null"); Debug.Assert(y != null, "y == null"); Debug.Assert(settings != null, "settings == null"); if (TryGetValueDiff(x, y, settings, out var diff)) { return(diff); } using (var borrow = DiffBuilder.GetOrCreate(x, y, settings)) { borrow.Value.UpdateDiffs(x, y, settings); return(borrow.Value.CreateValueDiffOrNull()); } }
private void AddDiffs( DiffBuilder collectionBuilder, IDictionary <TKey, TValue> x, IDictionary <TKey, TValue> y, MemberSettings settings) { using (var borrow = HashSetPool <TKey> .Borrow(EqualityComparer <TKey> .Default.Equals, EqualityComparer <TKey> .Default.GetHashCode)) { borrow.Value.UnionWith(x.Keys); borrow.Value.UnionWith(y.Keys); foreach (var key in borrow.Value) { var xv = x.ElementAtOrMissing(key); var yv = y.ElementAtOrMissing(key); collectionBuilder.UpdateCollectionItemDiff(xv, yv, key, settings); } } }
private static void AddItemDiffs(DiffBuilder collectionBuilder, ISet <T> x, ISet <T> y, HashSet <T> borrow) { borrow.UnionWith(x); if (borrow.SetEquals(y)) { return; } borrow.ExceptWith(y); foreach (var xi in borrow) { collectionBuilder.Add(new IndexDiff(xi, new ValueDiff(xi, PaddedPairs.MissingItem))); } borrow.Clear(); borrow.UnionWith(y); borrow.ExceptWith(x); foreach (var yi in borrow) { collectionBuilder.Add(new IndexDiff(yi, new ValueDiff(PaddedPairs.MissingItem, yi))); } }
/// <summary> /// Initializes a new instance of the <see cref="DirtyTrackerNode"/> class. /// A call to Initialize is needed after the ctor due to that we need to fetch child nodes and the graph can contain self /// </summary> private DirtyTrackerNode(IRefCounted <ReferencePair> refCountedPair, PropertiesSettings settings, bool isRoot) { this.refCountedPair = refCountedPair; var x = refCountedPair.Value.X; var y = refCountedPair.Value.Y; this.children = ChildNodes <DirtyTrackerNode> .Borrow(); this.xNode = RootChanges.GetOrCreate(x, settings, isRoot); this.yNode = RootChanges.GetOrCreate(y, settings, isRoot); this.xNode.Value.PropertyChange += this.OnTrackedPropertyChange; this.yNode.Value.PropertyChange += this.OnTrackedPropertyChange; this.IsTrackingCollectionItems = Is.Enumerable(x, y) && !settings.IsImmutable(x.GetType().GetItemType()) && !settings.IsImmutable(y.GetType().GetItemType()); if (Is.NotifyingCollections(x, y)) { this.xNode.Value.Add += this.OnTrackedAdd; this.xNode.Value.Remove += this.OnTrackedRemove; this.xNode.Value.Replace += this.OnTrackedReplace; this.xNode.Value.Move += this.OnTrackedMove; this.xNode.Value.Reset += this.OnTrackedReset; this.yNode.Value.Add += this.OnTrackedAdd; this.yNode.Value.Remove += this.OnTrackedRemove; this.yNode.Value.Replace += this.OnTrackedReplace; this.yNode.Value.Move += this.OnTrackedMove; this.yNode.Value.Reset += this.OnTrackedReset; } var builder = DiffBuilder.GetOrCreate(x, y, settings); builder.Value.UpdateDiffs(x, y, settings); builder.Value.Refresh(); this.refcountedDiffBuilder = builder; this.isDirty = !this.Builder.IsEmpty; }
// ReSharper disable once UnusedParameter.Local private void AddDiffs( DiffBuilder collectionBuilder, ISet <T> x, ISet <T> y, MemberSettings settings) { if (typeof(T).Implements <IEquatable <T> >()) { using (var borrow = HashSetPool <T> .Borrow(EqualityComparer <T> .Default.Equals, EqualityComparer <T> .Default.GetHashCode)) { AddItemDiffs(collectionBuilder, x, y, borrow.Value); return; } } switch (settings.ReferenceHandling) { case ReferenceHandling.Throw: throw Throw.ShouldNeverGetHereException("ReferenceHandling should be checked before"); case ReferenceHandling.References: using (var borrow = HashSetPool <T> .Borrow((xi, yi) => ReferenceEquals(xi, yi), item => RuntimeHelpers.GetHashCode(item))) { AddItemDiffs(collectionBuilder, x, y, borrow.Value); return; } case ReferenceHandling.Structural: using (var borrow = HashSetPool <T> .Borrow((xi, yi) => EqualBy.MemberValues(xi, yi, settings), xi => 0)) { AddItemDiffs(collectionBuilder, x, y, borrow.Value); return; } default: throw new ArgumentOutOfRangeException(); } }
internal static void UpdateMemberDiff( this DiffBuilder builder, object xSource, object ySource, MemberInfo member, MemberSettings settings) { if (settings.IsIgnoringMember(member)) { return; } var getterAndSetter = settings.GetOrCreateGetterAndSetter(member); if (getterAndSetter.TryGetValueEquals(xSource, ySource, settings, out var equal, out var xValue, out var yValue)) { if (equal) { builder.Remove(member); } else { builder.TryAdd(member, xValue, yValue); } return; } switch (settings.ReferenceHandling) { case ReferenceHandling.References: if (ReferenceEquals(xValue, yValue)) { builder.Remove(member); } else { builder.TryAdd(member, xValue, yValue); } return; case ReferenceHandling.Structural: IRefCounted <DiffBuilder> subDiffBuilder; if (DiffBuilder.TryCreate(xValue, yValue, settings, out subDiffBuilder)) { subDiffBuilder.Value.UpdateDiffs(xValue, yValue, settings); } builder.AddLazy(member, subDiffBuilder.Value); return; case ReferenceHandling.Throw: throw Throw.ShouldNeverGetHereException(); default: throw new ArgumentOutOfRangeException( nameof(settings.ReferenceHandling), settings.ReferenceHandling, null); } }