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 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); }
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); } }
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); }
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); } }
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); }
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); }
public void IsImmutable(Type type, bool expected) { var settings = PropertiesSettings.GetOrCreate(); var isImmutable = settings.IsImmutable(type); Assert.AreEqual(expected, isImmutable); }
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); }
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)); }
public void CheckNotifiesWhenValid(Type type) { var settings = PropertiesSettings.GetOrCreate(); var errors = ErrorBuilder.Start() .CheckNotifies(type, settings) .Finnish(); Assert.IsNull(errors); }
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; }
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); }
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)); }
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); }
public void WithExplicitImmutableAndComparer() { var settings = PropertiesSettings.Build() .AddImmutableType <IntCollection>() .AddComparer(IntCollection.Comparer) .CreateSettings(); Track.VerifyCanTrackIsDirty <With <IntCollection> >(settings); }
public void CheckReferenceHandlingWhenValid(Type type) { var settings = PropertiesSettings.GetOrCreate(); var errors = ErrorBuilder.Start() .CheckRequiresReferenceHandling(type, settings, _ => false) .Finnish(); Assert.IsNull(errors); }
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)); }
private static PropertiesSettings CreateChangeTrackerSettings() { var settings = PropertiesSettings.Build() .AddImmutableType <UnitParts>() .AddImmutableType <OperatorOverload>() .AddImmutableType <IEnumerable <IConversion> >() .CreateSettings(); return(settings); }
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 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); }
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)); }
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)); }
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); }
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)))); }
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); }
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); } } }
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)); } }
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; } }
internal static IRefCounted<RootChanges> GetOrCreate(INotifyCollectionChanged source, PropertiesSettings settings, bool isRoot) { return GetOrCreate((object)source, settings, isRoot); }
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)); }
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; }