Пример #1
0
        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);
        }
Пример #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;
        }
        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());
        }