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);
        }
Esempio n. 2
0
        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;
        }