public void CreateAndDisposeExplicitSetting(ReferenceHandling referenceHandling)
            {
                var x = new WithSimpleProperties { Value = 1, Time = DateTime.MinValue };
                var y = new WithSimpleProperties { Value = 1, Time = DateTime.MinValue };
                var propertyChanges = new List<string>();
                var expectedChanges = new List<string>();

                using (var tracker = Track.IsDirty(x, y, PropertiesSettings.GetOrCreate(referenceHandling)))
                {
                    tracker.PropertyChanged += (_, e) => propertyChanges.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                    Assert.AreEqual(null, tracker.Diff);
                    CollectionAssert.IsEmpty(propertyChanges);

                    x.Value++;
                    Assert.AreEqual(true, tracker.IsDirty);
                    Assert.AreEqual("WithSimpleProperties Value x: 2 y: 1", tracker.Diff.ToString("", " "));
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, propertyChanges);
                }

                x.Value++;
                CollectionAssert.AreEqual(expectedChanges, propertyChanges);

#if (!DEBUG) // debug build keeps instances alive longer for nicer debugging experience
                var wrx = new System.WeakReference(x);
                var wry = new System.WeakReference(y);
                x = null;
                y = null;
                System.GC.Collect();
                Assert.AreEqual(false, wrx.IsAlive);
                Assert.AreEqual(false, wry.IsAlive);
#endif
            }
            public void CreateAndDisposeExplicitSetting(ReferenceHandling referenceHandling)
            {
                var source = new WithSimpleProperties { Value1 = 1, Time = DateTime.MinValue };
                var propertyChanges = new List<string>();
                var expectedPropertyChanges = new List<string>();
                var changes = new List<EventArgs>();

                using (var tracker = Track.Changes(source, referenceHandling))
                {
                    tracker.PropertyChanged += (_, e) => propertyChanges.Add(e.PropertyName);
                    tracker.Changed += (_, e) => changes.Add(e);
                    CollectionAssert.IsEmpty(propertyChanges);
                    CollectionAssert.IsEmpty(changes);

                    source.Value1++;
                    Assert.AreEqual(1, tracker.Changes);
                    expectedPropertyChanges.AddRange(new[] { "Changes" });
                    CollectionAssert.AreEqual(expectedPropertyChanges, propertyChanges);
                    var expected = new[] { RootChangeEventArgs.Create(ChangeTrackerNode.GetOrCreate(source, tracker.Settings, false).Value, new PropertyChangeEventArgs(source, source.GetProperty(nameof(source.Value1)))) };
                    CollectionAssert.AreEqual(expected, changes, EventArgsComparer.Default);
                }

                source.Value1++;
                CollectionAssert.AreEqual(expectedPropertyChanges, propertyChanges);

#if (!DEBUG) // debug build keeps instances alive longer for nicer debugging experience
                var wrx = new System.WeakReference(source);
                source = null;
                System.GC.Collect();
                Assert.AreEqual(false, wrx.IsAlive);
#endif
            }
            public void HappyPath(ReferenceHandling referenceHandling)
            {
                var source = new WithSimpleProperties
                {
                    IntValue = 1,
                    NullableIntValue = 2,
                    StringValue = "3",
                    EnumValue = StringSplitOptions.RemoveEmptyEntries
                };
                var target = new WithSimpleProperties { IntValue = 3, NullableIntValue = 4 };
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    Assert.AreEqual(1, source.IntValue);
                    Assert.AreEqual(1, target.IntValue);
                    Assert.AreEqual(2, source.NullableIntValue);
                    Assert.AreEqual(2, target.NullableIntValue);
                    Assert.AreEqual("3", source.StringValue);
                    Assert.AreEqual("3", target.StringValue);
                    Assert.AreEqual(StringSplitOptions.RemoveEmptyEntries, source.EnumValue);
                    Assert.AreEqual(StringSplitOptions.RemoveEmptyEntries, target.EnumValue);

                    source.IntValue = 5;
                    Assert.AreEqual(5, source.IntValue);
                    Assert.AreEqual(5, target.IntValue);
                }

                source.IntValue = 6;
                Assert.AreEqual(6, source.IntValue);
                Assert.AreEqual(5, target.IntValue);
            }
            public void CreateAndDispose(ReferenceHandling referenceHandling)
            {
                var x = new ObservableCollection<ComplexType> { new ComplexType("a", 1), new ComplexType("b", 2) };
                var y = new ObservableCollection<ComplexType>();
                var changes = new List<string>();
                using (var tracker = Track.IsDirty(x, y, referenceHandling))
                {
                    tracker.PropertyChanged += (_, e) => changes.Add(e.PropertyName);
                    Assert.AreEqual(true, tracker.IsDirty);
                    var expected = "ObservableCollection<ComplexType> [0] x: Gu.State.Tests.DirtyTrackerTypes+ComplexType y: missing item [1] x: Gu.State.Tests.DirtyTrackerTypes+ComplexType y: missing item";
                    var actual = tracker.Diff.ToString(""," ");
                    Assert.AreEqual(expected, actual);
                    CollectionAssert.IsEmpty(changes);
                }

                x.Add(new ComplexType("c", 3));
                CollectionAssert.IsEmpty(changes);

                x[0].Value++;
                CollectionAssert.IsEmpty(changes);

                x[1].Value++;
                CollectionAssert.IsEmpty(changes);

                x[2].Value++;
                CollectionAssert.IsEmpty(changes);
            }
            public void Excludes(ReferenceHandling referenceHandling)
            {
                var source = new WithSimpleProperties { IntValue = 1, StringValue = "2" };
                var target = new WithSimpleProperties { IntValue = 3, StringValue = "4" };
                var settings = PropertiesSettings.Build()
                                                 .IgnoreProperty<WithSimpleProperties>(x => x.StringValue)
                                                 .CreateSettings(referenceHandling);
                using (Synchronize.PropertyValues(source, target, settings))
                {
                    Assert.AreEqual(1, source.IntValue);
                    Assert.AreEqual(1, target.IntValue);
                    Assert.AreEqual("2", source.StringValue);
                    Assert.AreEqual("4", target.StringValue);

                    source.IntValue = 5;
                    Assert.AreEqual(5, source.IntValue);
                    Assert.AreEqual(5, target.IntValue);

                    source.StringValue = "7";
                    Assert.AreEqual("7", source.StringValue);
                    Assert.AreEqual("4", target.StringValue);
                }

                source.IntValue = 6;
                Assert.AreEqual(6, source.IntValue);
                Assert.AreEqual(5, target.IntValue);
                Assert.AreEqual("7", source.StringValue);
                Assert.AreEqual("4", target.StringValue);
            }
            public void Add(ReferenceHandling referenceHandling)
            {
                var source = new ObservableCollection<int>();
                var propertyChanges = new List<string>();
                var changes = new List<EventArgs>();
                using (var tracker = Track.Changes(source, referenceHandling))
                {
                    tracker.PropertyChanged += (_, e) => propertyChanges.Add(e.PropertyName);
                    tracker.Changed += (_, e) => changes.Add(e);
                    Assert.AreEqual(0, tracker.Changes);
                    CollectionAssert.IsEmpty(propertyChanges);
                    CollectionAssert.IsEmpty(changes);

                    source.Add(1);
                    Assert.AreEqual(1, tracker.Changes);
                    CollectionAssert.AreEqual(new[] { "Changes" }, propertyChanges);
                    var node = ChangeTrackerNode.GetOrCreate((INotifyCollectionChanged)source, tracker.Settings, false).Value;
                    var expected = new[] { RootChangeEventArgs.Create(node, new AddEventArgs(source, 0)) };
                    CollectionAssert.AreEqual(expected, changes, EventArgsComparer.Default);

                    source.Add(2);
                    Assert.AreEqual(2, tracker.Changes);
                    CollectionAssert.AreEqual(new[] { "Changes", "Changes" }, propertyChanges);
                    expected = new[]
                                   {
                                       RootChangeEventArgs.Create(node, new AddEventArgs(source, 0)),
                                       RootChangeEventArgs.Create(node, new AddEventArgs(source, 1))
                                   };
                    CollectionAssert.AreEqual(expected, changes, EventArgsComparer.Default);
                }
            }
 public void Insert(ReferenceHandling referenceHandling)
 {
     var source = new ObservableCollection<int> { 1, 2 };
     var target = new ObservableCollection<int> { 1, 2 };
     using (Synchronize.PropertyValues(source, target, referenceHandling))
     {
         source.Insert(1, 3);
         CollectionAssert.AreEqual(new[] { 1, 3, 2 }, source);
         CollectionAssert.AreEqual(new[] { 1, 3, 2 }, target);
     }
 }
 public void ThrowsIfTargetCollectionChanges(ReferenceHandling referenceHandling)
 {
     var source = new ObservableCollection<int> { 1, 2 };
     var target = new ObservableCollection<int> { 1, 2 };
     using (Synchronize.PropertyValues(source, target, referenceHandling))
     {
         var exception = Assert.Throws<InvalidOperationException>(() => target.Add(3));
         var expected = "Target cannot be modified when a synchronizer is applied to it\r\n" +
                        "The change would just trigger a dirty notification and the value would be updated with the value from source.";
         Assert.AreEqual(expected, exception.Message);
     }
 }
 public void Add(ReferenceHandling referenceHandling)
 {
     var source = new ObservableCollection<WithGetReadOnlyPropertySealed<int>>();
     var target = new ObservableCollection<WithGetReadOnlyPropertySealed<int>>();
     using (Synchronize.PropertyValues(source, target, referenceHandling))
     {
         source.Add(new WithGetReadOnlyPropertySealed<int>(1));
         var expected = new[] { new WithGetReadOnlyPropertySealed<int>(1) };
         CollectionAssert.AreEqual(expected, source);
         CollectionAssert.AreEqual(expected, target);
         Assert.AreSame(source[0], target[0]);
     }
 }
            public void CreateAndDispose(ReferenceHandling referenceHandling)
            {
                var source = new ObservableCollection<int> { 1, 2 };
                var target = new ObservableCollection<int>();
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    var expected = new[] { 1, 2 };
                    CollectionAssert.AreEqual(expected, source);
                    CollectionAssert.AreEqual(expected, target);
                }

                source.Add(3);
                CollectionAssert.AreEqual(new[] { 1, 2, 3 }, source);
                CollectionAssert.AreEqual(new[] { 1, 2 }, target);
            }
            public void Remove(ReferenceHandling referenceHandling)
            {
                var source = new ObservableCollection<int> { 1, 2 };
                var target = new ObservableCollection<int> { 1, 2 };
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    source.RemoveAt(1);
                    CollectionAssert.AreEqual(new[] { 1 }, source);
                    CollectionAssert.AreEqual(new[] { 1 }, target);

                    source.RemoveAt(0);
                    CollectionAssert.IsEmpty(source);
                    CollectionAssert.IsEmpty(target);
                }
            }
 //[TestCase(ReferenceHandling.Reference)]
 public void Remove(ReferenceHandling referenceHandling)
 {
     var source = new WithObservableCollectionProperties(new ComplexType("a", 1), new ComplexType("b", 2));
     var target = new WithObservableCollectionProperties(new ComplexType("a", 1), new ComplexType("b", 2));
     using (Synchronize.PropertyValues(source, target, referenceHandling))
     {
         source.Complexes.RemoveAt(1);
         var expected = new[] { new ComplexType("a", 1) };
         CollectionAssert.AreEqual(expected, source.Complexes, ComplexType.Comparer);
         CollectionAssert.AreEqual(expected, target.Complexes, ComplexType.Comparer);
         source.Complexes.RemoveAt(0);
         CollectionAssert.IsEmpty(source.Complexes);
         CollectionAssert.IsEmpty(target.Complexes);
     }
 }
            public void Add(ReferenceHandling referenceHandling)
            {
                var source = new ObservableCollection<int>();
                var target = new ObservableCollection<int>();
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    source.Add(1);
                    CollectionAssert.AreEqual(new[] { 1 }, source);
                    CollectionAssert.AreEqual(new[] { 1 }, target);
                }

                source.Add(2);
                CollectionAssert.AreEqual(new[] { 1, 2 }, source);
                CollectionAssert.AreEqual(new[] { 1 }, target);
            }
            public void CreateAndDisposeWhenTargetIsEmpty(ReferenceHandling referenceHandling)
            {
                var source = new ObservableCollection<WithGetReadOnlyPropertySealed<int>> { new WithGetReadOnlyPropertySealed<int>(1), new WithGetReadOnlyPropertySealed<int>(2) };
                var target = new ObservableCollection<WithGetReadOnlyPropertySealed<int>>();
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    var expected = new[] { new WithGetReadOnlyPropertySealed<int>(1), new WithGetReadOnlyPropertySealed<int>(2) };
                    CollectionAssert.AreEqual(expected, source);
                    CollectionAssert.AreEqual(expected, target);
                    Assert.AreSame(source[0], target[0]);
                    Assert.AreSame(source[1], target[1]);
                }

                source.Add(new WithGetReadOnlyPropertySealed<int>(3));
                CollectionAssert.AreEqual(new[] { new WithGetReadOnlyPropertySealed<int>(1), new WithGetReadOnlyPropertySealed<int>(2), new WithGetReadOnlyPropertySealed<int>(3) }, source);
                CollectionAssert.AreEqual(new[] { new WithGetReadOnlyPropertySealed<int>(1), new WithGetReadOnlyPropertySealed<int>(2) }, target);
            }
            //[TestCase(ReferenceHandling.Reference)]
            public void Add(ReferenceHandling referenceHandling)
            {
                var source = new WithObservableCollectionProperties();
                var target = new WithObservableCollectionProperties();
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    source.Complexes.Add(new ComplexType("a", 1));
                    var expected = new[] { new ComplexType("a", 1) };
                    CollectionAssert.AreEqual(expected, source.Complexes, ComplexType.Comparer);
                    CollectionAssert.AreEqual(expected, target.Complexes, ComplexType.Comparer);

                    source.Complexes[0].Value++;
                    expected = new[] { new ComplexType("a", 2) };
                    CollectionAssert.AreEqual(expected, source.Complexes, ComplexType.Comparer);
                    CollectionAssert.AreEqual(expected, target.Complexes, ComplexType.Comparer);
                }
            }
            public void WithCalculated(ReferenceHandling referenceHandling)
            {
                var source = new WithCalculatedProperty { Value = 1 };
                var target = new WithCalculatedProperty { Value = 3 };
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    Assert.AreEqual(1, source.Value);
                    Assert.AreEqual(1, target.Value);

                    source.Value = 5;
                    Assert.AreEqual(5, source.Value);
                    Assert.AreEqual(5, target.Value);
                }

                source.Value = 6;
                Assert.AreEqual(6, source.Value);
                Assert.AreEqual(5, target.Value);
            }
            public void Tracks(ReferenceHandling referenceHandling)
            {
                var x = new WithImmutableProperty();
                var y = new WithImmutableProperty();
                var changes = new List<string>();
                var expectedChanges = new List<string>();
                using (var tracker = Track.IsDirty(x, y, referenceHandling))
                {
                    tracker.PropertyChanged += (_, e) => changes.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                    Assert.AreEqual(null, tracker.Diff);
                    CollectionAssert.IsEmpty(changes);

                    x.Name = "newName1";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithImmutableProperty Name x: newName1 y: null", tracker.Diff.ToString("", " "));

                    y.Name = "newName1";
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);

                    x.ImmutableValue = new WithGetReadOnlyPropertySealed<int>(1);
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithImmutableProperty ImmutableValue x: Gu.State.Tests.DirtyTrackerTypes+WithGetReadOnlyPropertySealed`1[System.Int32] y: null", tracker.Diff.ToString("", " "));

                    y.ImmutableValue = new WithGetReadOnlyPropertySealed<int>(1);
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);

                    x.ImmutableValue = new WithGetReadOnlyPropertySealed<int>(2);
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithImmutableProperty ImmutableValue x: Gu.State.Tests.DirtyTrackerTypes+WithGetReadOnlyPropertySealed`1[System.Int32] y: Gu.State.Tests.DirtyTrackerTypes+WithGetReadOnlyPropertySealed`1[System.Int32]", tracker.Diff.ToString("", " "));
                }
            }
            public void HandlesNull(ReferenceHandling referenceHandling)
            {
                var x = new WithComplexProperty();
                var y = new WithComplexProperty();
                var changes = new List<string>();
                var expectedChanges = new List<string>();
                using (var tracker = Track.IsDirty(x, y, referenceHandling))
                {
                    tracker.PropertyChanged += (_, e) => changes.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                    Assert.AreEqual(null, tracker.Diff);
                    CollectionAssert.IsEmpty(changes);

                    x.ComplexType = new ComplexType("a", 1);
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    var expected = "WithComplexProperty ComplexType x: Gu.State.Tests.DirtyTrackerTypes+ComplexType y: null";
                    var actual = tracker.Diff.ToString("", " ");
                    Assert.AreEqual(expected, actual);

                    y.ComplexType = new ComplexType("a", 1);
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);

                    x.ComplexType = null;
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    expected = "WithComplexProperty ComplexType x: null y: Gu.State.Tests.DirtyTrackerTypes+ComplexType";
                    actual = tracker.Diff.ToString("", " ");
                    Assert.AreEqual(expected, actual);

                    y.ComplexType = null;
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);
                }
            }
        public void LoadImages(ReferenceHandling refHandling = ReferenceHandling.Undefined)
        {
            ImageFileNames = new ObservableCollection<string>();
            List<string> filesToRemove = new List<string>();
            List<string> filesToAdd = new List<string>();

            if(Directory.Exists(GalleryDirectory)){
                IEnumerable<string> availableFiles = from path in Directory.GetFiles(GalleryDirectory) select Path.GetFileName(path);

                // Add files if they are located in the gallery folder and handle the others as specified
                foreach (string fileName in Model.ImageFileNames) {
                    if (availableFiles.Contains(fileName)) {
                        filesToAdd.Add(fileName);
                    }
                    else {
                        if (refHandling == ReferenceHandling.Undefined) {
                            // Let the user decide how to handle references to non-existing files
                            ErrorMessage fileNotFound = new ErrorMessage("File Not Found Error",
                                "File \"" + fileName + "\" not found. Do you want to proceed and remove all non-existent files from the gallery?",
                                new Dictionary<string, UndoableCommand> { {"Yes", LoadValidImagesCommand}, {"Keep references", LoadAllFilesCommand}, {"Cancel", null} });
                            mediator.ShowMessage(fileNotFound);
                            return;
                        }
                        else if (refHandling == ReferenceHandling.RemoveNonExisting) {
                            // Do not add the file to the view model's collection and remove its reference from the model
                            filesToRemove.Add(fileName);
                        }
                        else { // if(refHandling == ReferenceHandling.KeepNonExisting)
                            // Add the file anyway and ignore that it does not exist
                            filesToAdd.Add(fileName);
                        }
                    }
                }
                foreach (string file in filesToAdd) {
                    ImageFileNames.Add(file);
                    Console.WriteLine(file);
                }
                Model.ImageFileNames.RemoveAll(file => filesToRemove.Contains(file));
                RaisePropertyChanged("ImageFileNames");
            }
        }
            public void WithImmutable(ReferenceHandling referenceHandling)
            {
                var source = new With<Immutable>();

                var propertyChanges = new List<string>();
                var changes = new List<EventArgs>();

                using (var tracker = Track.Changes(source, referenceHandling))
                {
                    tracker.PropertyChanged += (_, e) => propertyChanges.Add(e.PropertyName);
                    tracker.Changed += (_, e) => changes.Add(e);
                    CollectionAssert.IsEmpty(propertyChanges);
                    CollectionAssert.IsEmpty(changes);

                    source.Value = new Immutable();
                    Assert.AreEqual(1, tracker.Changes);
                    CollectionAssert.AreEqual(new[] { "Changes" }, propertyChanges);
                    var node = ChangeTrackerNode.GetOrCreate(source, tracker.Settings, false).Value;
                    var expected = new[] { RootChangeEventArgs.Create(node, new PropertyChangeEventArgs(source, source.GetProperty(nameof(source.Value)))) };
                    CollectionAssert.AreEqual(expected, changes, EventArgsComparer.Default);
                }
            }
            public void TracksNested(ReferenceHandling referenceHandling)
            {
                var x = new Level { Next = new Level { Next = new Level { Name = "a" } } };
                var y = new Level { Next = new Level { Next = new Level { Name = "a" } } };
                var changes = new List<string>();
                var expectedChanges = new List<string>();
                using (var tracker = Track.IsDirty(x, y, referenceHandling))
                {
                    tracker.PropertyChanged += (_, e) => changes.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                    Assert.AreEqual(null, tracker.Diff);
                    CollectionAssert.IsEmpty(changes);

                    x.Name = "newName1";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("Level Name x: newName1 y: null", tracker.Diff.ToString("", " "));

                    y.Name = "newName1";
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);

                    x.Next.Next.Name = "b";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("Level Next Next Name x: b y: a", tracker.Diff.ToString("", " "));

                    y.Next.Next.Name = "b";
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);
                }
            }
Beispiel #22
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MemberSettings"/> class.
        /// </summary>
        /// <param name="ignoredMembers">A collection of members to ignore. Can be null.</param>
        /// <param name="ignoredTypes">A collection of types to ignore. Can be null.</param>
        /// <param name="immutableTypes">A collection of types to treat as immutable. Can be null.</param>
        /// <param name="comparers">A map of types with custom comparers. Can be null.</param>
        /// <param name="copyers">A map of custom copy implementations for types. Can be null.</param>
        /// <param name="referenceHandling">How reference values are handled.</param>
        /// <param name="bindingFlags">The bindingflags used for getting members.</param>
        protected MemberSettings(
            IEnumerable<MemberInfo> ignoredMembers,
            IEnumerable<Type> ignoredTypes,
            IEnumerable<Type> immutableTypes,
            IReadOnlyDictionary<Type, CastingComparer> comparers,
            IReadOnlyDictionary<Type, CustomCopy> copyers,
            ReferenceHandling referenceHandling,
                        BindingFlags bindingFlags)
        {
            this.ReferenceHandling = referenceHandling;
            this.BindingFlags = bindingFlags;
            if (ignoredMembers != null)
            {
                foreach (var ignoredMember in ignoredMembers)
                {
                    this.ignoredMembers.TryAdd(ignoredMember, true);
                }
            }

            this.ignoredTypes = IgnoredTypes.Create(ignoredTypes);
            this.immutableTypes = ImmutableSet<Type>.Create(immutableTypes);
            this.comparers = comparers;
            this.copyers = copyers;
        }
 public BindingFlagsAndReferenceHandling(BindingFlags bindingFlags, ReferenceHandling referenceHandling)
 {
     this.bindingFlags      = bindingFlags;
     this.referenceHandling = referenceHandling;
 }
            public void Replace(ReferenceHandling referenceHandling)
            {
                var source = new ObservableCollection<int> { 1, 2 };
                var target = new ObservableCollection<int> { 1, 2 };
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    source[0] = 3;
                    CollectionAssert.AreEqual(new[] { 3, 2 }, source);
                    CollectionAssert.AreEqual(new[] { 3, 2 }, target);

                    source[1] = 4;
                    CollectionAssert.AreEqual(new[] { 3, 4 }, source);
                    CollectionAssert.AreEqual(new[] { 3, 4 }, target);
                }
            }
            public void Replace(ReferenceHandling referenceHandling)
            {
                var source = new ObservableCollection<ComplexType> { new ComplexType("a", 1), new ComplexType("b", 2) };
                var target = new ObservableCollection<ComplexType> { new ComplexType("a", 1), new ComplexType("b", 2) };
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    source[0] = new ComplexType("c", 3);
                    var expected = new[] { new ComplexType("c", 3), new ComplexType("b", 2) };
                    CollectionAssert.AreEqual(expected, source, ComplexType.Comparer);
                    CollectionAssert.AreEqual(expected, target, ComplexType.Comparer);

                    source[1] = new ComplexType("d", 4);
                    expected = new[] { new ComplexType("c", 3), new ComplexType("d", 4) };
                    CollectionAssert.AreEqual(expected, source, ComplexType.Comparer);
                    CollectionAssert.AreEqual(expected, target, ComplexType.Comparer);
                }
            }
            public void MoveThenUpdate(ReferenceHandling referenceHandling)
            {
                var source = new ObservableCollection<ComplexType> { new ComplexType("a", 1), new ComplexType("b", 2), new ComplexType("c", 3) };
                var target = new ObservableCollection<ComplexType> { new ComplexType("a", 1), new ComplexType("b", 2), new ComplexType("c", 3) };
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    source.Move(2, 0);
                    var expected = new[] { new ComplexType("c", 3), new ComplexType("a", 1), new ComplexType("b", 2) };
                    CollectionAssert.AreEqual(expected, source, ComplexType.Comparer);
                    CollectionAssert.AreEqual(expected, target, ComplexType.Comparer);

                    source[0].Value++;
                    expected = new[] { new ComplexType("c", 4), new ComplexType("a", 1), new ComplexType("b", 2) };
                    CollectionAssert.AreEqual(expected, source, ComplexType.Comparer);
                    CollectionAssert.AreEqual(expected, target, ComplexType.Comparer);

                    source[1].Value++;
                    expected = new[] { new ComplexType("c", 4), new ComplexType("a", 2), new ComplexType("b", 2) };
                    CollectionAssert.AreEqual(expected, source, ComplexType.Comparer);
                    CollectionAssert.AreEqual(expected, target, ComplexType.Comparer);

                    source[2].Value++;
                    expected = new[] { new ComplexType("c", 4), new ComplexType("a", 2), new ComplexType("b", 3) };
                    CollectionAssert.AreEqual(expected, source, ComplexType.Comparer);
                    CollectionAssert.AreEqual(expected, target, ComplexType.Comparer);
                }
            }
Beispiel #27
0
 public abstract Diff DiffMethod <T>(T x, T y, ReferenceHandling referenceHandling = ReferenceHandling.Structural, string excludedMembers = null, Type excludedType = null);
 public void WithSimpleProperties(ReferenceHandling referenceHandling)
 {
     Track.VerifyCanTrackChanges<WithSimpleProperties>(referenceHandling);
     Track.VerifyCanTrackChanges<WithSimpleProperties>(PropertiesSettings.GetOrCreate(referenceHandling));
     Track.VerifyCanTrackChanges(typeof(WithSimpleProperties), PropertiesSettings.GetOrCreate(referenceHandling));
 }
 public void Caches(BindingFlags bindingFlags, ReferenceHandling referenceHandling)
 {
     var settings = PropertiesSettings.GetOrCreate(referenceHandling, bindingFlags);
     Assert.AreEqual(bindingFlags, settings.BindingFlags);
     Assert.AreEqual(referenceHandling, settings.ReferenceHandling);
     var second = PropertiesSettings.GetOrCreate(referenceHandling, BindingFlags.Public);
     Assert.AreSame(settings, second);
 }
 public AbstractDictionaryConverter(JsonSerializerOptions options)
 {
     _keyConverter      = options.GetDictionaryKeyConverterRegistry().GetDictionaryKeyConverter <TK>();
     _valueConverter    = (JsonConverter <TV>)options.GetConverter(typeof(TV));
     _referenceHandling = typeof(TV).IsStruct() ? ReferenceHandling.Default : options.GetReferenceHandling();
 }
            public void TracksNested(ReferenceHandling referenceHandling)
            {
                var x = new WithComplexProperty();
                var y = new WithComplexProperty();
                var changes = new List<string>();
                var expectedChanges = new List<string>();
                using (var tracker = Track.IsDirty(x, y, referenceHandling))
                {
                    tracker.PropertyChanged += (_, e) => changes.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                    Assert.AreEqual(null, tracker.Diff);
                    CollectionAssert.IsEmpty(changes);

                    x.Name = "newName1";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty Name x: newName1 y: null", tracker.Diff.ToString("", " "));

                    y.Name = "newName1";
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);

                    x.ComplexType = new ComplexType("a", 1);
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType x: Gu.State.Tests.DirtyTrackerTypes+ComplexType y: null", tracker.Diff.ToString("", " "));

                    y.ComplexType = new ComplexType("a", 1);
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);

                    x.ComplexType.Name = "newName2";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType Name x: newName2 y: a", tracker.Diff.ToString("", " "));

                    x.ComplexType.Value++;
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.Add("Diff");
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType Name x: newName2 y: a Value x: 2 y: 1", tracker.Diff.ToString("", " "));

                    y.ComplexType.Name = "newName2";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.Add("Diff");
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType Value x: 2 y: 1", tracker.Diff.ToString("", " "));

                    y.ComplexType.Value++;
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);
                }
            }
            public void HandlesMissingProperty(ReferenceHandling referenceHandling)
            {
                var source = new WithSimpleProperties { IntValue = 1, StringValue = "2" };
                var target = new WithSimpleProperties { IntValue = 3, StringValue = "4" };
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    Assert.AreEqual(1, source.IntValue);
                    Assert.AreEqual(1, target.IntValue);
                    Assert.AreEqual("2", source.StringValue);
                    Assert.AreEqual("2", target.StringValue);
                    source.OnPropertyChanged("Missing");
                    source.IntValue = 5;
                    Assert.AreEqual(5, source.IntValue);
                    Assert.AreEqual(5, target.IntValue);
                    Assert.AreEqual("2", source.StringValue);
                    Assert.AreEqual("2", target.StringValue);
                }

                source.IntValue = 6;
                Assert.AreEqual(6, source.IntValue);
                Assert.AreEqual(5, target.IntValue);
                Assert.AreEqual("2", source.StringValue);
                Assert.AreEqual("2", target.StringValue);
            }
Beispiel #33
0
        public override bool EqualByMethod <T, TValue>(T x, T y, IEqualityComparer <TValue> comparer, ReferenceHandling referenceHandling = ReferenceHandling.Structural)
        {
            var settings = PropertiesSettings.Build()
                           .AddComparer(comparer)
                           .CreateSettings(referenceHandling);

            return(EqualBy.PropertyValues(x, y, settings));
        }
Beispiel #34
0
            public void TracksNested(ReferenceHandling referenceHandling)
            {
                var x               = new WithComplexProperty();
                var y               = new WithComplexProperty();
                var changes         = new List <string>();
                var expectedChanges = new List <string>();

                using (var tracker = Track.IsDirty(x, y, referenceHandling))
                {
                    tracker.PropertyChanged += (_, e) => changes.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                    Assert.AreEqual(null, tracker.Diff);
                    CollectionAssert.IsEmpty(changes);

                    x.Name = "newName1";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty Name x: newName1 y: null", tracker.Diff.ToString("", " "));

                    y.Name = "newName1";
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);

                    x.ComplexType = new ComplexType("a", 1);
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType x: Gu.State.Tests.DirtyTrackerTypes+ComplexType y: null", tracker.Diff.ToString("", " "));

                    y.ComplexType = new ComplexType("a", 1);
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);

                    x.ComplexType.Name = "newName2";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType Name x: newName2 y: a", tracker.Diff.ToString("", " "));

                    x.ComplexType.Value++;
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.Add("Diff");
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType Name x: newName2 y: a Value x: 2 y: 1", tracker.Diff.ToString("", " "));

                    y.ComplexType.Name = "newName2";
                    Assert.AreEqual(true, tracker.IsDirty);
                    expectedChanges.Add("Diff");
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual("WithComplexProperty ComplexType Value x: 2 y: 1", tracker.Diff.ToString("", " "));

                    y.ComplexType.Value++;
                    Assert.AreEqual(false, tracker.IsDirty);
                    expectedChanges.AddRange(new[] { "Diff", "IsDirty" });
                    CollectionAssert.AreEqual(expectedChanges, changes);
                    Assert.AreEqual(null, tracker.Diff);
                }
            }
 public static JsonSerializerOptions SetReferenceHandling(this JsonSerializerOptions options, ReferenceHandling referenceHandling)
 {
     options.GetState().ReferenceHandling = referenceHandling;
     return(options);
 }
            public void Remove(ReferenceHandling referenceHandling)
            {
                var source = new ObservableCollection<WithGetReadOnlyPropertySealed<int>> { new WithGetReadOnlyPropertySealed<int>(1), new WithGetReadOnlyPropertySealed<int>(2) };
                var target = new ObservableCollection<WithGetReadOnlyPropertySealed<int>> { new WithGetReadOnlyPropertySealed<int>(1), new WithGetReadOnlyPropertySealed<int>(2) };
                using (Synchronize.PropertyValues(source, target, referenceHandling))
                {
                    source.RemoveAt(1);
                    var expected = new[] { new WithGetReadOnlyPropertySealed<int>(1) };
                    CollectionAssert.AreEqual(expected, source);
                    CollectionAssert.AreEqual(expected, target);

                    source.RemoveAt(0);
                    CollectionAssert.IsEmpty(source);
                    CollectionAssert.IsEmpty(target);
                }
            }
Beispiel #37
0
        public override bool EqualByMethod <T, TValue>(T x, T y, IEqualityComparer <TValue> comparer, ReferenceHandling referenceHandling = ReferenceHandling.Structural)
        {
            var builder = FieldsSettings.Build();

            builder.AddComparer(comparer);
            var settings = builder.CreateSettings(referenceHandling);

            return(EqualBy.FieldValues(x, y, settings));
        }