private void PostBoot() { _ApplyPatches = StateTreeAction.CreateActionInvoker <IJsonPatch[]> ( StoredValue, "@APPLY_PATCHES", (IJsonPatch[] patches) => { foreach (var patch in patches) { var paths = patch.Path.SplitJsonPath(); var node = this.ResolveNodeByPaths(paths.Take(paths.Length - 1)); (node as ObjectNode).ApplyPatchLocally(paths[paths.Length - 1], patch); } } ); _ApplySnapshot = StateTreeAction.CreateActionInvoker <object> ( StoredValue, "@APPLY_SNAPSHOT", (object snapshot) => { // if the snapshot is the same as the current one, avoid performing a reconcile if (snapshot != Snapshot) { // apply it by calling the type logic Type.ApplySnapshot(this, snapshot); } } ); }
protected void FinalizeNewInstance(INode node, IMap <string, INode> childNodes) { var instance = node.StoredValue as IObservableObject <T, INode>; // Node = node as ObjectNode; if (instance != null) { foreach (var property in childNodes) { instance.Write(property.Key, property.Value); } foreach (var initializer in Initializers) { initializer(instance); } if (instance is IObservableObject <T, INode> observable) { foreach (var action in Actions) { observable.AddAction(action.Name, StateTreeAction.CreateActionInvoker(instance, action.Name, action.Action)); } foreach (var hook in Hooks) { var hookAction = (Action <object[]>)Delegate.Combine(hook.Value.ToArray()); observable.AddAction(hook.Key.ToString(), Observable.Actions.CreateAction(hook.Key.ToString(), (arguments) => { hookAction(new object[] { instance }.Concat(arguments).ToArray()); return(null); })); } //Actions.RunInAction(call.Name, action, new object[] { call.Target }.Concat(call.Arguments).ToArray()) } instance.Intercept(change => WillChange(change)); instance.Observe(change => DidChange(change)); } }
public static IDisposable OnAction(this object target, Action <ISerializedActionCall> listener, bool attachAfter = true) { if (!target.IsStateTreeNode()) { throw new InvalidOperationException("Can not listen for action on Non State Tree Node"); } void FireListener(IMiddlewareEvent call) { if (call.Type == MiddlewareEventType.Action && call.Id == call.RootId) { var source = call.Context.GetStateTreeNode(); var data = new SerializedActionCall { Name = call.Name, Path = StateTreeUtils.GetRelativePathBetweenNodes(target.GetStateTreeNode(), source), //TODO: serialize arguments Arguments = call.Arguments.ToArray() }; listener(data); } } Action <IMiddlewareEvent, Action <IMiddlewareEvent, Func <object, object> >, Action <object> > onAfterAction = (IMiddlewareEvent call, Action <IMiddlewareEvent, Func <object, object> > next, Action <object> action) => { next(call, null); FireListener(call); }; Action <IMiddlewareEvent, Action <IMiddlewareEvent, Func <object, object> >, Action <object> > onBeforeAction = (IMiddlewareEvent call, Action <IMiddlewareEvent, Func <object, object> > next, Action <object> action) => { FireListener(call); next(call, null); }; return(StateTreeAction.AddMiddleware(target.GetStateTree(), attachAfter ? onAfterAction : onBeforeAction)); }