public static bool AreSame(INode oldNode, object newValue) { // the new value has the same node if (newValue.IsStateTreeNode()) { return(newValue.GetStateTreeNode() == oldNode); } if (StateTreeUtils.IsMutatble(newValue) && oldNode.Snapshot == newValue) { return(true); } if (oldNode is ObjectNode oNode) { if (!string.IsNullOrWhiteSpace(oNode.Identifier) && !string.IsNullOrWhiteSpace(oNode.IdentifierAttribute)) { return(EqualityComparer <object> .Default.Equals(StateTreeUtils.GetPropertyValue(newValue, oNode.IdentifierAttribute), oNode.Identifier)); } } return(false); }
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; }