/// <summary> /// Adds or updates a tracked property state. /// </summary> /// <param name="property">The tracked property</param> /// <param name="targetObject">The object owning the tracked property</param> public void AddOrUpdateTracking(PropertyInfo property, object targetObject = null) { Contract.Requires(() => property != null, "Since this is tracking a property, the property itself cannot be null"); Contract.Requires(() => targetObject == null || property.DeclaringType.IsAssignableFrom(targetObject.GetType()), "Given property must be declared on the given target object"); lock (_syncLock) { targetObject = targetObject ?? TargetObject; object currentValue = targetObject.GetType().GetProperty(property.Name, DefaultBindingFlags) .GetValue(targetObject); DeclaredObjectPropertyChangeTracking existingTracking = null; Contract.Assert(() => PropertyTrackings != null, "Cannot add or update a tracking if tracking collection is null"); PropertyInfo baseProperty = property.GetBaseProperty(); DeclaredObjectPropertyChangeTracking tracking = null; if (Configuration.CanTrackProperty(property) && !PropertyTrackings.TryGetValue(baseProperty, out existingTracking)) { DeclaredObjectPropertyChangeTracking declaredTracking = new DeclaredObjectPropertyChangeTracking(Configuration, TrackableObjectFactory, this, targetObject, baseProperty, property, currentValue); tracking = declaredTracking; PropertyTrackings.Add(baseProperty, declaredTracking); } else if (existingTracking != null) { existingTracking.CurrentValue = currentValue; tracking = existingTracking; } if (tracking != null && tracking.HasChanged) { _Changed?.Invoke(this, new DeclaredObjectPropertyChangeEventArgs(targetObject, tracking)); } } }
public IObjectGraphTrackingInfo GetTrackingGraphFromProperty(PropertyInfo property) { DeclaredObjectPropertyChangeTracking propertyTracking = null; PropertyTrackings.TryGetValue(property.GetBaseProperty(), out propertyTracking); List <IDeclaredObjectPropertyChangeTracking> hierarchy = new List <IDeclaredObjectPropertyChangeTracking>(); bool searchTracking = true; while (searchTracking) { hierarchy.Add(propertyTracking); var result = PropertyTrackings.SingleOrDefault ( t => t.Value.CurrentValue == propertyTracking.TargetObject && t.Value.Property.PropertyType.GetProperty(propertyTracking.Property.Name) == propertyTracking.Property.GetBaseProperty() ); if (result.Value != null) { propertyTracking = result.Value; property = propertyTracking.Property; } else { searchTracking = false; } } Contract.Assert(() => propertyTracking != null); return(new ObjectGraphTrackingInfo ( propertyTracking.TargetObject, hierarchy.Reverse <IDeclaredObjectPropertyChangeTracking>().ToImmutableList() )); }