public IdentifierCache SplitCache(ObjectNode node) { var result = new IdentifierCache(); var path = node.Path; var values = node.IdentifierCache.Cache.Values; foreach (var nodes in values) { for (int i = nodes.Count - 1; i >= 0; i--) { if (nodes[i].Path.IndexOf(path) == 0) { result.AddNodeToCache(nodes[i]); nodes.RemoveAt(i); } } } return(this); }
public ObjectNode(IType type, ObjectNode parent, string subpath, IEnvironment environment, object initialSnapshot, Func <object, IStateTreeNode, object> createNewInstance, Action <INode, object, IStateTreeNode> finalizeNewInstance = null) { NodeId = ++NextNodeId; Type = type; //_initialSnapshot = initialSnapshot; //_createNewInstance = createNewInstance; //_finalizeNewInstance = finalizeNewInstance; State = NodeLifeCycle.INITIALIZING; SubpathAtom = new Atom("path"); Subpath = subpath; EscapedSubpath = subpath.EscapeJsonPath(); Parent = parent; Environment = environment; _IsRunningAction = false; IsProtectionEnabled = true; AutoUnbox = true; PreBoot(); if (type is IObjectType objectType) { IdentifierAttribute = objectType.IdentifierAttribute; // identifier can not be changed during lifecycle of a node // so we safely can read it from initial snapshot if (!string.IsNullOrWhiteSpace(IdentifierAttribute)) { Identifier = Convert.ToString(StateTreeUtils.GetPropertyValue(initialSnapshot, IdentifierAttribute)); } } if (parent == null) { IdentifierCache = new IdentifierCache(); } var childNodes = type.InitializeChildNodes(this, initialSnapshot); if (parent == null) { IdentifierCache.AddNodeToCache(this); } else { parent.Root.IdentifierCache.AddNodeToCache(this); } IStateTreeNode meta = new StateTreeNode(this); StoredValue = createNewInstance(childNodes, meta); PostBoot(); PreCompute(); bool sawException = true; try { _IsRunningAction = true; finalizeNewInstance?.Invoke(this, childNodes, meta); _IsRunningAction = false; FireHook(Hook.AfterCreate); State = NodeLifeCycle.CREATED; sawException = false; } finally { if (sawException) { // short-cut to die the instance, to avoid the snapshot computed starting to throw... State = NodeLifeCycle.DEAD; } } // NOTE: we need to touch snapshot, because non-observable // "observableInstanceCreated" field was touched // _Snapshot.TrackAndCompute(); if (IsRoot) { AddSnapshotReaction(); } FinalizeCreation(); // _childNodes = null; // _initialSnapshot = null; // _createNewInstance = null; // _finalizeNewInstance = null; }
public ObjectNode(IType type, ObjectNode parent, string subpath, IEnvironment environment, object initialValue, object storedValue, bool canAttachTreeNode, Action <INode, object> finalize) { NodeId = ++NextNodeId; Type = type; StoredValue = storedValue; _SubPath = ObservableValue <string> .From(); Subpath = subpath; _Parent = ObservableValue <ObjectNode> .From(); Parent = parent; Environment = environment; _IsRunningAction = false; IsProtectionEnabled = true; AutoUnbox = true; State = NodeLifeCycle.INITIALIZING; PreBoot(); PreCompute(); if (parent == null) { IdentifierCache = new IdentifierCache(); } if (canAttachTreeNode) { NodeCache.Add(StoredValue, new StateTreeNode(this)); } bool sawException = true; try { _IsRunningAction = true; finalize?.Invoke(this, initialValue); _IsRunningAction = false; if (parent != null) { parent.Root.IdentifierCache?.AddNodeToCache(this); } else { IdentifierCache?.AddNodeToCache(this); } FireHook("afterCreate"); State = NodeLifeCycle.CREATED; sawException = false; } finally { if (sawException) { // short-cut to die the instance, to avoid the snapshot computed starting to throw... State = NodeLifeCycle.DEAD; } } var disposer = Reactions.Reaction <object>((r) => Snapshot, (snapshot, r) => EmitSnapshot(snapshot)); AddDisposer(() => disposer.Dispose()); }