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);
            }
예제 #2
0
            public void WithIllegal()
            {
                var expected = // "Track.Changes(x, y) failed for item: ObservableCollection<ComplexType>[0].Illegal.\r\n" +
                               "Track.Changes(x, y) failed.\r\n" +
                               "The type IllegalType does not notify changes.\r\n" +
                               "The property WithIllegal.Illegal of type IllegalType is not supported.\r\n" +
                               "Solve the problem by any of:\r\n" +
                               "* Implement INotifyPropertyChanged for IllegalType or use a type that does.\r\n" +
                               "* Make IllegalType immutable or use an immutable type.\r\n" +
                               "  - For immutable types the following must hold:\r\n" +
                               "    - Must be a sealed class or a struct.\r\n" +
                               "    - All fields and properties must be readonly.\r\n" +
                               "    - All field and property types must be immutable.\r\n" +
                               "    - All indexers must be readonly.\r\n" +
                               "    - Event fields are ignored.\r\n" +
                               "* Use PropertiesSettings and specify how change tracking is performed:\r\n" +
                               "  - ReferenceHandling.Structural means that a the entire graph is tracked.\r\n" +
                               "  - ReferenceHandling.References means that only the root level changes are tracked.\r\n" +
                               "  - Exclude a combination of the following:\r\n" +
                               "    - The property WithIllegal.Illegal.\r\n" +
                               "    - The type IllegalType.\r\n";

                var item      = new WithIllegal();
                var settings  = PropertiesSettings.GetOrCreate();
                var exception = Assert.Throws <NotSupportedException>(() => Track.Changes(item, settings));

                Assert.AreEqual(expected, exception.Message);

                exception = Assert.Throws <NotSupportedException>(() => Track.Changes(item));
                Assert.AreEqual(expected, exception.Message);
            }
예제 #3
0
            public void CheckReferenceHandlingWhenRootError(bool requiresRef)
            {
                var settings = PropertiesSettings.GetOrCreate(ReferenceHandling.Throw);
                var type     = typeof(List <ComplexType>);
                var errors   = ErrorBuilder.Start()
                               .CheckRequiresReferenceHandling(type, settings, _ => requiresRef)
                               .Finnish();

                if (requiresRef)
                {
                    var error    = RequiresReferenceHandling.Enumerable;
                    var expected = new[] { error };
                    CollectionAssert.AreEqual(expected, errors.Errors);
                    var stringBuilder = new StringBuilder();
                    var message       = stringBuilder.AppendNotSupported(errors)
                                        .ToString();
                    var expectedMessage = "";
                    Assert.AreEqual(expectedMessage, message);

                    stringBuilder = new StringBuilder();
                    message       = stringBuilder.AppendSuggestExclude(errors)
                                    .ToString();
                    expectedMessage = "";
                    Assert.AreEqual(expectedMessage, message);
                }
                else
                {
                    Assert.AreEqual(null, errors);
                }
            }
예제 #4
0
            public void WithComplexProperty()
            {
                var x = new WithComplexProperty {
                    ComplexType = new ComplexType("a", 1)
                };
                var y = new WithComplexProperty {
                    ComplexType = new ComplexType("a", 1)
                };
                var changes  = new List <string>();
                var settings = PropertiesSettings.GetOrCreate();

                using (var tracker = Track.IsDirty(x, y, settings))
                {
                    tracker.PropertyChanged += (_, e) => changes.Add(e.PropertyName);
                    Assert.AreEqual(false, tracker.IsDirty);
                }

                x.ComplexType = new ComplexType("b", 2);
                CollectionAssert.IsEmpty(changes);

                var wrx  = new System.WeakReference(x);
                var wrxc = new System.WeakReference(x.ComplexType);
                var wry  = new System.WeakReference(y);
                var wryc = new System.WeakReference(y.ComplexType);

                x = null;
                y = null;
                System.GC.Collect();
                Assert.AreEqual(false, wrx.IsAlive);
                Assert.AreEqual(false, wrxc.IsAlive);
                Assert.AreEqual(false, wry.IsAlive);
                Assert.AreEqual(false, wryc.IsAlive);
            }
예제 #5
0
            public void IgnoresBaseClassPropertyLambda()
            {
                var source   = new DerivedClass();
                var settings = PropertiesSettings.Build()
                               .IgnoreProperty <ComplexType>(x => x.Excluded)
                               .CreateSettings(ReferenceHandling.Structural);

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

                using (var tracker = Track.Changes(source, settings))
                {
                    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.Value++;
                    Assert.AreEqual(1, tracker.Changes);
                    CollectionAssert.AreEqual(new[] { "Changes" }, propertyChanges);
                    var expected = new[] { RootChangeEventArgs.Create(ChangeTrackerNode.GetOrCreate(source, tracker.Settings, isRoot: false).Value, new PropertyChangeEventArgs(source, source.GetProperty(nameof(source.Value)))) };
                    CollectionAssert.AreEqual(expected, changes, EventArgsComparer.Default);

                    source.Excluded++;
                    Assert.AreEqual(1, tracker.Changes);
                    CollectionAssert.AreEqual(new[] { "Changes" }, propertyChanges);
                    CollectionAssert.AreEqual(expected, changes, EventArgsComparer.Default);
                }
            }
예제 #6
0
        public override void CopyMethod <T>(
            T source,
            T target,
            ReferenceHandling referenceHandling = ReferenceHandling.Structural,
            string excluded    = null,
            Type ignoredType   = null,
            Type immutableType = null)
        {
            var builder = PropertiesSettings.Build();

            if (excluded != null)
            {
                builder.IgnoreProperty <T>(excluded);
            }

            if (ignoredType != null)
            {
                builder.IgnoreType(ignoredType);
            }

            if (immutableType != null)
            {
                builder.AddImmutableType(immutableType);
            }

            var settings = builder.CreateSettings(referenceHandling);

            Copy.PropertyValues(source, target, settings);
        }
예제 #7
0
파일: Classes.cs 프로젝트: forki/Gu.State
        public override Diff DiffMethod <T>(
            T x,
            T y,
            ReferenceHandling referenceHandling = ReferenceHandling.Structural,
            string excludedMembers = null,
            Type ignoredType       = null,
            Type immutableType     = null)
        {
            var builder = PropertiesSettings.Build();

            if (excludedMembers != null)
            {
                builder.IgnoreProperty <T>(excludedMembers);
            }

            if (ignoredType != null)
            {
                builder.IgnoreType(ignoredType);
            }

            if (immutableType != null)
            {
                builder.AddImmutableType(immutableType);
            }

            var settings = builder.CreateSettings(referenceHandling);

            return(DiffBy.PropertyValues(x, y, settings));
        }
            public void CheckIndexersWhenError()
            {
                var settings = PropertiesSettings.GetOrCreate();
                var type     = typeof(ErrorTypes.WithIndexer);
                var errors   = ErrorBuilder.Start()
                               .CheckIndexers(type, settings)
                               .Finnish();
                var indexer  = type.GetProperties().Single();
                var error    = UnsupportedIndexer.GetOrCreate(indexer);
                var expected = new[] { error };

                CollectionAssert.AreEqual(expected, errors.Errors);
                var stringBuilder = new StringBuilder();
                var message       = stringBuilder.AppendNotSupported(errors)
                                    .ToString();
                var expectedMessage = "Indexers are not supported.\r\n" +
                                      "  - The property WithIndexer.Item is an indexer and not supported.\r\n";

                Assert.AreEqual(expectedMessage, message);

                stringBuilder = new StringBuilder();
                message       = stringBuilder.AppendSuggestExclude(errors)
                                .ToString();
                expectedMessage = "  - Exclude a combination of the following:\r\n" +
                                  "    - The indexer property WithIndexer.Item.\r\n";
                Assert.AreEqual(expectedMessage, message);
            }
예제 #9
0
        public void IsImmutable(Type type, bool expected)
        {
            var settings    = PropertiesSettings.GetOrCreate();
            var isImmutable = settings.IsImmutable(type);

            Assert.AreEqual(expected, isImmutable);
        }
예제 #10
0
        public override void VerifyMethod <T>(
            ReferenceHandling referenceHandling,
            string excludedMembers = null,
            Type ignoredType       = null,
            Type immutableType     = null)
        {
            var builder = PropertiesSettings.Build();

            if (excludedMembers != null)
            {
                builder.IgnoreProperty <T>(excludedMembers);
            }

            if (ignoredType != null)
            {
                builder.AddImmutableType(ignoredType);
            }

            if (immutableType != null)
            {
                builder.AddImmutableType(immutableType);
            }

            var settings = builder.CreateSettings(referenceHandling);

            Copy.VerifyCanCopyPropertyValues <T>(settings);
        }
 internal Synchronizer(INotifyPropertyChanged source, INotifyPropertyChanged target, PropertiesSettings settings)
 {
     this.Settings = settings;
     this.dirtyTrackerNode = DirtyTrackerNode.GetOrCreate(source, target, settings, true);
     this.dirtyTrackerNode.Value.Changed += this.OnDirtyTrackerNodeChanged;
     this.borrowedQueue = ConcurrentQueuePool<DirtyTrackerNode>.Borrow();
     this.AddToSyncQueue(this.dirtyTrackerNode.Value);
 }
예제 #12
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));
        }
 public void IgnoresPropertyCtor()
 {
     var type = typeof(SettingsTypes.ComplexType);
     var nameProperty = type.GetProperty(nameof(SettingsTypes.ComplexType.Name));
     var valueProperty = type.GetProperty(nameof(SettingsTypes.ComplexType.Value));
     var settings = new PropertiesSettings(new[] { nameProperty }, null, null, null, null, ReferenceHandling.Throw, Constants.DefaultPropertyBindingFlags);
     Assert.AreEqual(true, settings.IsIgnoringProperty(nameProperty));
     Assert.AreEqual(false, settings.IsIgnoringProperty(valueProperty));
 }
예제 #14
0
            public void CheckNotifiesWhenValid(Type type)
            {
                var settings = PropertiesSettings.GetOrCreate();
                var errors   = ErrorBuilder.Start()
                               .CheckNotifies(type, settings)
                               .Finnish();

                Assert.IsNull(errors);
            }
예제 #15
0
 public ChangeTracker(INotifyPropertyChanged source, PropertiesSettings settings)
 {
     Ensure.NotNull(source, nameof(source));
     Ensure.NotNull(settings, nameof(settings));
     Track.Verify.CanTrackType(source.GetType(), settings);
     this.Settings = settings;
     this.node = ChangeTrackerNode.GetOrCreate(source, settings, true);
     this.node.Value.Changed += this.OnNodeChange;
 }
예제 #16
0
        public void GetRecursive()
        {
            var x        = new object();
            var y        = new object();
            var settings = PropertiesSettings.GetOrCreate();
            var rec      = TrackerCache.GetOrAdd(x, y, settings, p => new Recursive(p, settings));

            Assert.AreSame(rec, rec.Value.Next);
        }
예제 #17
0
        public void IgnoresInterfaceProperty()
        {
            var settings = PropertiesSettings.Build()
                           .IgnoreProperty <SettingsTypes.IComplexType>(x => x.Name)
                           .CreateSettings();

            Assert.AreEqual(true, settings.IsIgnoringProperty(typeof(SettingsTypes.ComplexType).GetProperty(nameof(SettingsTypes.ComplexType.Name))));
            Assert.AreEqual(true, settings.IsIgnoringProperty(typeof(SettingsTypes.IComplexType).GetProperty(nameof(SettingsTypes.ComplexType.Name))));
        }
        public void Equals(string xs, string ys, bool expected)
        {
            var x        = xs.Split(',').Select(int.Parse);
            var y        = ys.Split(',').Select(int.Parse);
            var comparer = EnumerableEqualByComparer <int> .Default;
            var settings = PropertiesSettings.GetOrCreate();

            Assert.AreEqual(expected, comparer.Equals(x, y, settings, null));
        }
예제 #19
0
        public void ReturnsDifferentForDifferentSettings()
        {
            var x  = new ComplexType();
            var y  = new ComplexType();
            var t1 = DiffBuilder.GetOrCreate(x, y, PropertiesSettings.GetOrCreate(ReferenceHandling.Structural));
            var t2 = DiffBuilder.GetOrCreate(x, y, PropertiesSettings.GetOrCreate(ReferenceHandling.Throw));

            Assert.AreNotSame(t1, t2);
        }
예제 #20
0
            public void WithExplicitImmutableAndComparer()
            {
                var settings = PropertiesSettings.Build()
                               .AddImmutableType <IntCollection>()
                               .AddComparer(IntCollection.Comparer)
                               .CreateSettings();

                Track.VerifyCanTrackIsDirty <With <IntCollection> >(settings);
            }
예제 #21
0
            public void CheckReferenceHandlingWhenValid(Type type)
            {
                var settings = PropertiesSettings.GetOrCreate();
                var errors   = ErrorBuilder.Start()
                               .CheckRequiresReferenceHandling(type, settings, _ => false)
                               .Finnish();

                Assert.IsNull(errors);
            }
예제 #22
0
        public void IgnoresPropertyCtor()
        {
            var type          = typeof(SettingsTypes.ComplexType);
            var nameProperty  = type.GetProperty(nameof(SettingsTypes.ComplexType.Name));
            var valueProperty = type.GetProperty(nameof(SettingsTypes.ComplexType.Value));
            var settings      = new PropertiesSettings(new[] { nameProperty }, null, null, null, null, ReferenceHandling.Throw, Constants.DefaultPropertyBindingFlags);

            Assert.AreEqual(true, settings.IsIgnoringProperty(nameProperty));
            Assert.AreEqual(false, settings.IsIgnoringProperty(valueProperty));
        }
예제 #23
0
        private static PropertiesSettings CreateChangeTrackerSettings()
        {
            var settings = PropertiesSettings.Build()
                           .AddImmutableType <UnitParts>()
                           .AddImmutableType <OperatorOverload>()
                           .AddImmutableType <IEnumerable <IConversion> >()
                           .CreateSettings();

            return(settings);
        }
예제 #24
0
        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);
        }
예제 #25
0
            public void CheckReferenceHandlingWhenPropertyError()
            {
                var settings = PropertiesSettings.GetOrCreate(ReferenceHandling.Throw);
                var type     = typeof(With <List <int> >);
                var errors   = ErrorBuilder.Start()
                               .CheckRequiresReferenceHandling(type, settings, _ => true)
                               .Finnish();
                var expected = new[] { RequiresReferenceHandling.ComplexType };

                CollectionAssert.AreEqual(expected, errors.Errors);
            }
예제 #26
0
        public void IgnoresPropertyBuilder()
        {
            var type          = typeof(SettingsTypes.ComplexType);
            var nameProperty  = type.GetProperty(nameof(SettingsTypes.ComplexType.Name));
            var valueProperty = type.GetProperty(nameof(SettingsTypes.ComplexType.Value));
            var settings      = PropertiesSettings.Build()
                                .IgnoreProperty(nameProperty)
                                .CreateSettings();

            Assert.AreEqual(true, settings.IsIgnoringProperty(nameProperty));
            Assert.AreEqual(false, settings.IsIgnoringProperty(valueProperty));
        }
예제 #27
0
        public void IgnoresIndexer()
        {
            var type            = typeof(SettingsTypes.WithIndexerType);
            var nameProperty    = type.GetProperty(nameof(SettingsTypes.WithIndexerType.Name));
            var indexerProperty = type.GetProperties().Single(x => x.GetIndexParameters().Length > 0);
            var settings        = PropertiesSettings.Build()
                                  .IgnoreIndexersFor <SettingsTypes.WithIndexerType>()
                                  .CreateSettings();

            Assert.AreEqual(false, settings.IsIgnoringProperty(nameProperty));
            Assert.AreEqual(true, settings.IsIgnoringProperty(indexerProperty));
        }
예제 #28
0
        public void WithSpecialCopyPropertyWhenNull()
        {
            var source   = new With <WithReadonlyProperty <int> >(new WithReadonlyProperty <int>(1));
            var target   = new With <WithReadonlyProperty <int> >();
            var settings = PropertiesSettings.Build()
                           .AddCustomCopy <WithReadonlyProperty <int> >((x, y) => new WithReadonlyProperty <int>(5))
                           .CreateSettings();

            Copy.PropertyValues(source, target, settings);
            Assert.AreEqual(1, source.Value.Value);
            Assert.AreEqual(5, target.Value.Value);
        }
예제 #29
0
        public void IgnoresBaseTypeBuilder()
        {
            var settings = PropertiesSettings.Build()
                           .IgnoreType <SettingsTypes.ComplexType>()
                           .CreateSettings();

            Assert.AreEqual(true, settings.IsIgnoringProperty(typeof(SettingsTypes.ComplexType).GetProperty(nameof(SettingsTypes.ComplexType.Name))));
            Assert.AreEqual(true, settings.IsIgnoringProperty(typeof(SettingsTypes.ComplexType).GetProperty(nameof(SettingsTypes.ComplexType.Value))));
            Assert.AreEqual(true, settings.IsIgnoringProperty(typeof(SettingsTypes.Derived).GetProperty(nameof(SettingsTypes.Derived.Name))));
            Assert.AreEqual(true, settings.IsIgnoringProperty(typeof(SettingsTypes.Derived).GetProperty(nameof(SettingsTypes.Derived.Value))));
            Assert.AreEqual(false, settings.IsIgnoringProperty(typeof(SettingsTypes.Derived).GetProperty(nameof(SettingsTypes.Derived.DoubleValue))));
        }
예제 #30
0
        public void IgnoresBaseClassPropertyLambda()
        {
            var settings = PropertiesSettings.Build()
                           .IgnoreProperty <SettingsTypes.ComplexType>(x => x.Name)
                           .CreateSettings();
            var nameProperty = typeof(SettingsTypes.ComplexType).GetProperty(nameof(SettingsTypes.ComplexType.Name));

            Assert.AreEqual(true, settings.IsIgnoringProperty(nameProperty));

            nameProperty = typeof(SettingsTypes.Derived).GetProperty(nameof(SettingsTypes.Derived.Name));
            Assert.AreEqual(true, settings.IsIgnoringProperty(nameProperty));
            Assert.AreEqual(false, settings.IsIgnoringProperty(typeof(SettingsTypes.Derived).GetProperty(nameof(SettingsTypes.Derived.Value))));
        }
            public void ReturnsDifferentForDifferentSettings()
            {
                var x = new WithSimpleProperties {
                    Value = 1, Time = DateTime.MinValue
                };
                var y = new WithSimpleProperties {
                    Value = 1, Time = DateTime.MinValue
                };
                var t1 = DirtyTrackerNode.GetOrCreate(x, y, PropertiesSettings.GetOrCreate(ReferenceHandling.Structural), true);
                var t2 = DirtyTrackerNode.GetOrCreate(x, y, PropertiesSettings.GetOrCreate(ReferenceHandling.References), true);

                Assert.AreNotSame(t1, t2);
            }
예제 #32
0
        public void ReturnsDifferentForDifferentPairs()
        {
            var x = new ComplexType();
            var y = new ComplexType();
            var structuralSettings = PropertiesSettings.GetOrCreate(ReferenceHandling.Structural);

            using (var t1 = DiffBuilder.GetOrCreate(x, y, structuralSettings))
            {
                using (var t2 = DiffBuilder.GetOrCreate(y, x, structuralSettings))
                {
                    Assert.AreNotSame(t1, t2);
                }
            }
        }
예제 #33
0
        public void IgnoresCollectionProperties(Type type)
        {
            var settings      = PropertiesSettings.GetOrCreate();
            var propertyInfos = type.GetProperties(Constants.DefaultFieldBindingFlags);

            if (type != typeof(int[]))
            {
                CollectionAssert.IsNotEmpty(propertyInfos);
            }

            foreach (var propertyInfo in propertyInfos)
            {
                Assert.AreEqual(true, settings.IsIgnoringProperty(propertyInfo));
            }
        }
예제 #34
0
        private RootChanges(object source, PropertiesSettings settings)
        {
            this.Source = source;
            this.Settings = settings;
            this.TrackProperties = this.Source.GetType()
                                       .GetProperties()
                                       .Where(p => !this.Settings.IsIgnoringProperty(p))
                                       .Where(p => !settings.IsImmutable(p.PropertyType))
                                       .ToArray();
            var inpc = source as INotifyPropertyChanged;
            if (inpc != null)
            {
                inpc.PropertyChanged += this.OnSourcePropertyChanged;
            }

            var incc = source as INotifyCollectionChanged;
            if (incc != null)
            {
                incc.CollectionChanged += this.OnSourceCollectionChanged;
            }
        }
예제 #35
0
 internal static IRefCounted<RootChanges> GetOrCreate(INotifyCollectionChanged source, PropertiesSettings settings, bool isRoot)
 {
     return GetOrCreate((object)source, settings, isRoot);
 }
예제 #36
0
        internal static IRefCounted<RootChanges> GetOrCreate(object source, PropertiesSettings settings, bool isRoot)
        {
            Debug.Assert(source != null, "Cannot track null");
            if (isRoot)
            {
                Track.Verify.CanTrackType(source.GetType(), settings);
            }
            else
            {
                Track.Verify.CanTrackValue(source, settings);
            }

            return TrackerCache.GetOrAdd(source, settings, s => new RootChanges(s, settings));
        }
예제 #37
0
 internal DirtyTracker(INotifyPropertyChanged x, INotifyPropertyChanged y, PropertiesSettings settings)
 {
     this.Settings = settings;
     this.node = DirtyTrackerNode.GetOrCreate(x, y, settings, true);
     this.node.Value.PropertyChanged += this.OnNodeChanged;
 }