/// <summary> /// Allows you to register a delegate that is called when the tracked objects change. /// </summary> /// <param name="source">The source.</param> /// <param name="onChangedDelegate">The on changed delegate.</param> public static void WhenChanged(this IEnumerable <ITrackableObject> source, Action onChangedDelegate) { TrackingCache cache = new TrackingCache(); foreach (ITrackableObject item in source) { WhenChanged(item, onChangedDelegate, cache); } }
public static void StartTracking(this IEnumerable <ITrackableObject> source) { TrackingCache propertyCache = new TrackingCache(); foreach (ITrackableObject item in source) { StartTracking(item, propertyCache); } }
private static bool ShouldAllowProperty(PropertyInfo property, TrackingCache cache) { bool result; if (cache.AllowedProperties.TryGetValue(property, out result)) { return(result); } result = ShouldAllowProperty(property); cache.AllowedProperties[property] = result; return(result); }
internal static void WhenChanged(ITrackableObject item, Action onChangedDelegate, TrackingCache cache) { if (onChangedDelegate == null) { throw new ArgumentNullException(nameof(onChangedDelegate)); } TrackingState tracker = GetTracker(item); tracker.OnChanged.Add(onChangedDelegate); PropertyInfo[] properties; if (!cache.Properties.TryGetValue(item.GetType(), out properties)) { properties = item.GetType().GetProperties(); cache.Properties[item.GetType()] = properties; } foreach (var property in properties) { if (property.PropertyType != typeof(TrackingState) && ShouldAllowProperty(property, cache)) { var value = property.GetValue(item); if (property.PropertyType.IsGenericType && property.PropertyType.IsAssignableTo(typeof(System.Collections.IEnumerable))) { System.Collections.IEnumerable list = (System.Collections.IEnumerable)value; foreach (object subItem in list) { ITrackableObject trackedItem = subItem as ITrackableObject; if (trackedItem != null) { WhenChanged(trackedItem, onChangedDelegate, cache); } } } } } }
public static void WhenChanged(this ITrackableObject item, Action onChangedDelegate) { TrackingCache cache = new TrackingCache(); WhenChanged(item, onChangedDelegate, cache); }
private static TrackingState StartTracking(ITrackableObject source, TrackingCache cache) { TrackingState tracker = new TrackingState(source); PropertyInfo[] properties; if (!cache.Properties.TryGetValue(source.GetType(), out properties)) { properties = source.GetType().GetProperties(); cache.Properties[source.GetType()] = properties; } foreach (var property in properties) { if (property.PropertyType != typeof(TrackingState) && ShouldAllowProperty(property, cache)) { var value = property.GetValue(source); if (property.PropertyType.IsGenericType && property.PropertyType.IsAssignableTo(typeof(System.Collections.IEnumerable))) { System.Collections.IEnumerable list = (System.Collections.IEnumerable)value; List <ITrackableObject> deletedItems = new List <ITrackableObject>(); foreach (object item in list) { ITrackableObject trackedItem = item as ITrackableObject; if (trackedItem != null) { if (trackedItem.IsTracking() && trackedItem.IsDeleted()) { deletedItems.Add(trackedItem); StopTracking(trackedItem); } else { StartTracking(trackedItem, cache); } } } //Remove any items we detected as having been deleted. IList editableList = list as IList; if (editableList != null) { foreach (var removeItem in deletedItems) { editableList.Remove(removeItem); } } } else if (property.PropertyType.IsAssignableTo(typeof(ITrackableObject))) { ITrackableObject trackedItem = value as ITrackableObject; if (trackedItem != null) { StartTracking(trackedItem, cache); } } tracker.UnmodifiedState.Add(property, value); } } trackedObjects[source] = tracker; return(tracker); }
public static TrackingState StartTracking(this ITrackableObject source) { TrackingCache cache = new TrackingCache(); return(StartTracking(source, cache)); }