Exemple #1
0
        /// <summary>
        /// Parse an <see cref="IStorable"/> listing all its children
        /// and the ones that changed.
        /// </summary>
        /// <param name="children">List of children.</param>
        /// <param name="changedStorables">List of storables with changes.</param>
        /// <param name="storable">The storable object to parse.</param>
        /// <param name="settings">The serialization settings.</param>
        /// <param name="reset">If set to <c>true</c> reset the IsChanged flag.</param>
        public bool Parse(out StorableNode parentNode, IStorable storable, JsonSerializerSettings settings,
                          bool reset = true)
        {
            bool ret = ParseInternal(out parentNode, storable, settings, reset);

            if (ret && current != null)
            {
                Log.Error("Stack should be empty");
                return(false);
            }
            parentNode.OrphanChildren = deletedStorables.Except(aliveStorables).ToList();
            deletedStorables.Clear();
            aliveStorables.Clear();
            return(ret);
        }
Exemple #2
0
 internal bool ParseInternal(out StorableNode parentNode, IStorable value, JsonSerializerSettings settings,
                             bool reset = true)
 {
     stack            = new Stack <object> ();
     parentNode       = new StorableNode(value);
     deletedStorables = new HashSet <IStorable> ();
     parsedCount      = 0;
     aliveStorables   = new HashSet <IStorable> ();
     resolver         = settings.ContractResolver ?? new DefaultContractResolver();
     this.reset       = reset;
     try {
         CheckValue(value, parentNode);
         return(true);
     } catch (Exception ex) {
         Log.Exception(ex);
         return(false);
     }
 }
Exemple #3
0
        void CheckValue(object value, StorableNode node = null)
        {
            IStorable storable;

            if (value == null)
            {
                return;
            }

            if (stack.Any(o => Object.ReferenceEquals(o, value)))
            {
                // Value in stack, return to avoid dependency cycles.
                return;
            }
            stack.Push(value);

            storable = value as IStorable;

            if (storable != null)
            {
                if (node == null)
                {
                    node = new StorableNode(storable);
                }
                // Update parent and children relations
                if (current != null)
                {
                    if (current.Deleted)
                    {
                        node.Deleted = true;
                    }
                    else
                    {
                        current.Children.Add(node);
                    }
                }
                if (!node.Deleted)
                {
                    aliveStorables.Add(storable);
                }
                node.Parent = current;
                current     = node;
            }

            // Figure out the type of object we are dealing with and parse it accordingly.
            // Primitives are ignored (not being objects containers) and lists and dictionaries
            // are traversed through all their children.
            JsonContract valueContract = resolver.ResolveContract(value.GetType());

            if (valueContract is JsonObjectContract)
            {
                CheckObject(value, valueContract as JsonObjectContract);
            }
            else if (valueContract is JsonArrayContract)
            {
                CheckEnumerable(value as IEnumerable, valueContract as JsonArrayContract);
            }
            else if (valueContract is JsonDictionaryContract)
            {
                CheckEnumerable((value as IDictionary).Values, valueContract as JsonArrayContract);
            }
            else
            {
                // Skip primitive value
            }

            // Now try to find orphaned objects and create nodes with the Deleted flags.
            // These objects are currently saved in the database and cached in IStorable.SavedChildren but
            // the current IStorable does not reference them anymore as real children.
            // We used this cache to find the orphaned children and mark them with the Deleted flag.
            if (storable != null)
            {
                if (storable.DeleteChildren && storable.SavedChildren != null)
                {
                    var orphaned = storable.SavedChildren.Except(node.Children.Select(n => n.Storable));
                    foreach (IStorable st in orphaned)
                    {
                        deletedStorables.Add(st);
                        StorableNode onode = new StorableNode(st);
                        onode.Deleted = true;
                        CheckValue(st, onode);
                    }
                }
                current = current.Parent;
            }
            stack.Pop();
        }