void ITransactedModelEvent.Rollback(ModelTransaction transaction) { Prepare(transaction); ModelEventScope.Perform(() => { ModelContext context = Instance.Type.Context; ModelInstanceList list = Instance.GetList(Property); if (Added != null) { foreach (ModelInstance item in Added) { list.Remove(item); } } if (Removed != null) { foreach (ModelInstance item in Removed) { list.Add(item); } } }); }
/// <summary> /// Creates a new model filter for the specified root object. /// </summary> /// <param name="root"></param> /// <param name="paths"></param> public ModelFilter(ModelInstance root, string[] paths) { // Store the model root this.root = root; // Delay model notifications while loading the model ModelEventScope.Perform(() => { // Subscribe to paths for each predicate ModelType rootType = root.Type; foreach (string p in paths) { // Get the path for this predicate ModelPath path = rootType.GetPath(p); // Skip this predicate if it is already being monitored if (pathModels.ContainsKey(path)) { continue; } // Subscribe to path change events path.Change += path_PathChanged; // Get the model for this path and add the path and model to the list of paths pathModels.Add(path, path.GetInstances(root)); } }); // Combine the models for each path into a universal model CombinePathModels(); }
/// <summary> /// Starts a new <see cref="ModelEventScope"/>, allows subclasses to perform /// event specific notifications by overriding <see cref="OnNotify"/>, and /// notifies the context that the event has occurred. /// </summary> virtual internal void Notify() { ModelEventScope.Perform(this, () => { instance.Type.Context.Notify(this); OnNotify(); }); }
/// <summary> /// Rolls back the current transaction by calling <see cref="ModelEvent.Revert"/> /// in reverse order on all model events that occurred during the transaction. /// </summary> public void Rollback() { IsActive = false; Context.Event -= context_Event; ModelEventScope.Perform(() => { for (var node = events.Last; node != null; node = node.Previous) { ((ITransactedModelEvent)node.Value).Rollback(this); } }); }
/// <summary> /// Performs all of the model events associated with the current transaction. /// </summary> public void Perform() { ModelEventScope.Perform(() => { foreach (var modelEvent in events) { ((ITransactedModelEvent)modelEvent).Perform(this); if (modelEvent is ModelInitEvent.InitNew) { RegisterNewInstance(modelEvent.Instance); } } }); }
/// <summary> /// Removes all of the instances from the list. /// </summary> public void Clear() { // Get the list and exit immediately if it does not contain any items IList list = GetList(); if (list == null || list.Count == 0) { return; } // Remove all of the items from the list ModelEventScope.Perform(() => { list.Clear(); }); }
/// <summary> /// Performs a set of previous changes, performs the specified operation, and records new changes that /// occur as a result of the previous changes and the specified operation. /// </summary> /// <param name="operation"></param> /// <param name="transaction"></param> /// <returns></returns> public ModelTransaction Perform(Action operation, ModelTransaction transaction) { // Create an event scope to track changes that occur as a result of applying previous changes ModelEventScope eventScope = new ModelEventScope(); try { // Perform previous changes Perform(); // Return the new changes that occurred while applying the previous changes return(Chain(transaction).Record(() => { // Allow model subscribers to be notified of the previous changes eventScope.Exit(); // Clear the reference to the event scope to ensure it is not disposed twice eventScope = null; // Perform the specified operation if (operation != null) { operation(); } })); } catch (Exception actionException) { try { if (eventScope != null) { eventScope.Exit(); } } catch (Exception disposalException) { throw new ModelEventScope.ScopeException(disposalException, actionException); } throw; } }
/// <summary> /// Invokes the <see cref="Exited"/> event if this is the outermost <see cref="ModelEventScope"/>. /// </summary> internal void Exit() { try { if (Exited != null) { if (parent != null) { parent.Exited += Exited; } else { RaiseExited(); } } } finally { // Set the current scope to the parent scope current = parent; } }
public ModelEventScopeExitedEventArgs(ModelEventScope scope) { this.scope = scope; }
/// <summary> /// Creates a new <see cref="ModelEventScope"/> that represents a generic event /// within the object model. /// </summary> internal ModelEventScope() { parent = current; current = this; }
/// <summary> /// Invokes the <see cref="Exited"/> event if this is the outermost <see cref="ModelEventScope"/>. /// </summary> internal void Exit() { try { if (Exited != null) { if (parent != null) parent.Exited += Exited; else RaiseExited(); } } finally { // Set the current scope to the parent scope current = parent; } }
internal override void Notify() { ModelEventScope.Perform(this, OnNotify); }