protected override void Attach() { TrackedObject.PropertyChanged += OnPropertyChanged; // Scan through the properties to see if we need to // observe nested objects; for each property add an // ObjectTracker. var properties = TrackedObject.GetType() .GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(prop => prop.GetIndexParameters().Length == 0) .Where(prop => !prop.CustomAttributes.Any(o => o.AttributeType == typeof(DoNotTrackAttribute))) .ToArray(); foreach (var prop in properties) { RefreshPropertyTracker(prop.Name, raiseEvent: false); // Do not raise events on initialization } }
private void RefreshPropertyTracker(string propertyName, bool raiseEvent) { // Determine the new value var prop = TrackedObject.GetType().GetProperty(propertyName); if (prop == null) { return; // Was probably an indexer that changed } var newValue = prop.GetValue(TrackedObject); // If no ObjectTracker exists for the property, the old value was null TrackerToken trackerToken; object oldValue = null; if (_propertyTrackers.TryGetValue(propertyName, out trackerToken)) { // Detach old tracker from old value and remove it oldValue = trackerToken.Tracker.TrackedObject; trackerToken.Dispose(); _propertyTrackers.Remove(propertyName); } if (newValue != null) { // Add a new tracker for the new value var token = new TrackerToken(newValue, propertyName, Tracker); _propertyTrackers.Add(propertyName, token); } // Notify that property changed if (raiseEvent) { Tracker.RaisePropertyPathChanged(new PropertyPathChangedEventArgs(propertyName, TrackedObject, oldValue, newValue)); } }
protected override void Attach() { if (!(TrackedObject is IEnumerable)) { throw new ArgumentException($"Failed to track collection changes on object of type {TrackedObject.GetType()}. The object does not implement {nameof(IEnumerable)}."); } TrackedObject.CollectionChanged += OnCollectionChanged; // Scan through the items and create an ObjectTracker // for each item. var i = 0; foreach (var item in TrackedObject as IEnumerable) { InsertTrackerAt(i++, item); } }