public static void SynchronizeProxiedForLifetime(this IObservableObject obj, ConsoleApp app, string propertyName, Action handler, ILifetimeManager manager) { obj.SynchronizeForLifetime(propertyName, () => { app.QueueAction(handler); }, manager); }
private void Watch(IObservableObject obj, string path = "root") { foreach (var existingTrackedProperty in trackedObservables.Where(o => o.Path.StartsWith(path)).ToList()) { trackedObservables.Remove(existingTrackedProperty); } var trackedObservable = new TrackedObservable() { PropertyValue = obj, Path = path }; trackedObservables.Add(trackedObservable); var trackingLifetime = trackedObservables.GetMembershipLifetime(trackedObservable); foreach (var property in obj.GetType().GetProperties()) { if (obj is IObservableCollection && property.Name == "Item") { continue; } bool isSyncing = true; obj.SynchronizeForLifetime(property.Name, () => { var myProp = property; var val = myProp.GetValue(obj); if (val is IObservableObject) { Watch(val as IObservableObject, path + "." + myProp.Name); } if (isSyncing) { isSyncing = false; } else { if (undoRedoPending == false) { undoRedoStack.Do(new PropertyAssignmentAction(obj, myProp, obj.GetPrevious(myProp.Name))); } Changed.Fire(); } }, trackingLifetime); } if (obj is IObservableCollection) { var collection = obj as IObservableCollection; collection .WhereAs <IObservableObject>() .ForEach(child => Watch(child as IObservableObject, path + "[" + Guid.NewGuid() + "]")); collection.Added.SubscribeForLifetime((o) => { if (undoRedoPending == false) { undoRedoStack.Do(new AddToCollectionAction(collection, o, collection.LastModifiedIndex)); } if (o is IObservableObject) { Watch(o as IObservableObject, path + "[" + Guid.NewGuid() + "]"); } Changed.Fire(); }, trackingLifetime); collection.Removed.SubscribeForLifetime((o) => { if (undoRedoPending == false) { undoRedoStack.Do(new RemovedFromCollectionAction(collection, o, collection.LastModifiedIndex)); } if (o is IObservableObject) { var tracked = trackedObservables.Where(to => to.PropertyValue == o).Single(); foreach (var related in trackedObservables.Where(t => t.Path.StartsWith(tracked.Path)).ToList()) { trackedObservables.Remove(related); } } Changed.Fire(); }, trackingLifetime); collection.AssignedToIndex.SubscribeForLifetime((args) => throw new NotSupportedException("Index assignments are not supported by observable documents"), trackingLifetime); } }