Exemplo n.º 1
0
        public object Serialize(object input)
        {
            // If Unity supported a modern C# version with, say, dynamic, we could go back to the overloaded methods approach
            // Instead of this giant mess of if-checks
            if (input is PrimitiveStructure)
            {
                return(((PrimitiveStructure)input).ToPrimitive());
            }
            ICollectionHandler referenced = serializerState.references.GetValueOrDefault(input);

            if (referenced != null)
            {
                return(MakeReference(referenced));
            }
            TypeHandler handler = registry.GetSerializer(input).CreateHandler(this);  // Will throw on unsupported types.

            if (handler is ICollectionHandler)
            {
                // It's important that the reference is set up BEFORE we serialize the handler, otherwise a nested reference to the input may fail to notice
                // the existing reference since we haven't created it yet.
                serializerState.references[input] = (ICollectionHandler)handler;
            }
            return(handler.ProxySerialize(input));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Helper function for resolving references.  Updates the passed list of references.  Returns a non-null value if the parent container should replace
        /// its current item with the returned item.
        /// </summary>
        /// <param name="references"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        internal IJsonDict ResolveItem(IJsonDict item)
        {
            object typeId   = GetTypeIdentifier(item);
            object objectId = item.GetValueOrDefault("ref");
            // Debug.Log(string.Format("Identified object of type {0} -- object ID: {1}", typeId, objectId));
            IJsonDict referenced = (objectId == null) ? null : deserializerState.references.GetValueOrDefault(objectId);

            if (typeId as string == "ref")   // Found a reference
            {
                if (objectId == null)
                {
                    throw new SerializationException("Found a missing or null reference ID.");
                }
                // This works because we don't want to replace if the item didn't exist (and thus would return NULL),
                // and we do want to replace if it did (and thus would return an actual value)
                if (referenced == null)
                {
                    // Debug.Log(string.Format("Adding new pending reference to {0}", objectId));
                    deserializerState.references[objectId] = item;
                }
                else
                {
                    // Debug.Log(string.Format("Replacing reference with actual object of type ", referenced["type"]));
                }
                return(referenced);
            }
            // Still here?  Okay.
            // Nested container check.
            TypeHandler handler = registry.GetDeserializer(typeId).CreateHandler(this);

            if (handler is ICollectionHandler)
            {
                // FIXME: See if this code is actually needed.
                if (item.ContainsKey("_visited"))
                {
                    Debug.LogWarning("*** WARNING ***: Container already visited.");
                }
                else
                {
                    item["_visited"] = true;
                    foreach (var container in ((ICollectionHandler)handler).GetContainers(item))
                    {
                        deserializerState.pending.Push(container);
                    }
                }
            }

            if (objectId == null)
            {
                return(null);                  // Unreferenced object, nothing to do.
            }
            if (referenced == null)
            {
                deserializerState.references[objectId] = item;
                // Debug.Log("Saving reference.");
            }
            else
            {
                // Already references something else.  Let's hope it's a reference.
                if (GetTypeIdentifier(referenced) as string != "ref")
                {
                    // ... nope.  Complain loudly.
                    throw new SerializationException(string.Format("Object reference '{0}' refers to multiple non-reference objects", objectId));
                }
                // Everything we've previously seen up until now points to the old object.  It's way too much of a hassle to replace it, so...
                // instead we clear it and copy all of our data to it.
                // Debug.Log(string.Format("Copying over to actual object of type ", referenced["type"]));
                referenced.Clear();
                foreach (JsonKey kvp in item)
                {
                    referenced[kvp.Key] = kvp.Value;    // Resistance is futile.  You will be assimilated.
                }
                // Debug.Log("Done copying over");
            }
            return(referenced);
        }