예제 #1
0
        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");
        }
예제 #2
0
 public void AddDiffs(
     DiffBuilder collectionBuilder,
     object x,
     object y,
     MemberSettings settings)
 {
     this.AddDiffs(collectionBuilder, (IEnumerable <T>)x, (IEnumerable <T>)y, settings);
 }
예제 #3
0
 public void AddDiffs(
     DiffBuilder collectionBuilder,
     object x,
     object y,
     MemberSettings settings)
 {
     this.AddDiffs(collectionBuilder, (Array)x, (Array)y, settings);
 }
예제 #4
0
 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);
 }
예제 #6
0
 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);
     }
 }
예제 #7
0
 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);
     }
 }
예제 #8
0
 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);
 }
예제 #9
0
 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);
     }
 }
예제 #10
0
 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);
     }
 }
예제 #11
0
        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);
            }
        }
예제 #12
0
        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);
        }
예제 #13
0
        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);
        }
예제 #14
0
        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);
            }
        }
예제 #15
0
        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);
         }
     }
 }
예제 #17
0
        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)));
            }
        }
예제 #18
0
        /// <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;
        }
예제 #19
0
        // 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();
            }
        }
예제 #20
0
        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);
            }
        }