private IMapWillChange <I, INode> WillChange(IMapWillChange <I, INode> change)
        {
            var node = change.Object.GetStateTreeNode() as ObjectNode;

            node.AssertWritable();

            var map = change.Object as IObservableMap <I, INode, T>;

            switch (change.Type)
            {
            case ChangeType.UPDATE:
            {
                var oldValue = map.GetValue(change.Name);

                if (change.NewValue == oldValue)
                {
                    return(null);
                }

                StateTreeUtils.Typecheck(SubType, change.NewValue.StoredValue);

                change.NewValue = SubType.Reconcile(node.GetChildNode(change.Name.ToString()), change.NewValue.StoredValue);

                ProcessIdentifier(change.Name.ToString(), change.NewValue);
            }
            break;

            case ChangeType.ADD:
            {
                StateTreeUtils.Typecheck(SubType, change.NewValue.StoredValue);

                change.NewValue = SubType.Instantiate(node, change.Name.ToString(), node.Environment, change.NewValue.StoredValue);

                ProcessIdentifier(change.Name.ToString(), change.NewValue);
            }
            break;
            }

            return(change);
        }
        public override IMap <string, INode> InitializeChildNodes(INode node, object snapshot)
        {
            IDictionary <I, S> values = snapshot as IDictionary <I, S>;

            //if (snapshot is IDictionary<string, S> dictionary)
            //{
            //    foreach(var item in dictionary.Keys)
            //    {
            //        values[item.ToString()] = dictionary[item];
            //    }
            //}

            IEnvironment env = node.Environment;

            return(values.Aggregate(new Map <string, INode>(), (map, pair) =>
            {
                var subpath = $"{pair.Key}";

                map[subpath] = SubType.Instantiate(node, subpath, env, pair.Value);

                return map;
            }));
        }