예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="surrogate"></param>
        /// <param name="obj"></param>
        /// <param name="firstChild"></param>
        /// <returns></returns>
        protected object DeserializeSurrogate(ISerializationSurrogate surrogate, Type objType, int objId, XmlNode firstChild, XmlElement rootElement, object standin)
        {
            //NOTE: Technically this isn't necessary because we can be sure it'll
            //never be called on Components. The GameObject surrogate will handle
            //deserializing components and any loose references will be skipped
            //until the deference phase at the end of deserialization.
            //However, in case serialization wasn't done properly (components were
            //serialized in-place rather than defered to GameObject serialization),
            //then we need to ensure we simply skip this in such a case.
            if (standin == null)
            {
                if (objType.IsSubclassOf(typeof(Component)))
                {
                    return(null);
                }
                if (objType.IsSubclassOf(typeof(Component[])))
                {
                    return(null);
                }
                if (objType == typeof(Component[]))
                {
                    return(null);
                }
            }

            SerializationInfo  info    = new SerializationInfo(objType, new DummyConverter());
            DeserializeContext context = new DeserializeContext();

            context.Deserializer             = this;
            context.ObjId                    = objId;
            context.ElementBeingParsed       = rootElement;
            context.ObjectType               = objType;
            context.deserializationObjCache  = this.deserializationObjCache;
            context.deserializationTypeCache = this.deserializationTypeCache;

            //float through the xml nodes and see what items we need to collect.
            for (XmlNode node = firstChild; node != null; node = node.NextSibling)
            {
                object val = DeserializeCore((XmlElement)node);
                if (val != null)
                {
                    info.AddValue(node.Name, val, val.GetType());
                }
                else
                {
                    info.AddValue(node.Name, null, typeof(object));
                }
            }

            //if the standin is null, we need to create an instance.
            //Otherwise, we were given an instance to work with.
            object obj = standin;

            if (obj == null)
            {
                if (SerializerBase.IsSameOrSubclass(typeof(MulticastDelegate), objType))
                {
                    obj = null;
                }
                else
                {
                    obj = CreateInstanceOfType(objType, false);
                    //if(SerializerBase.IsReferenceNull(obj))
                    //    return null;
                }
            }

            //we pass obj in but we also assign it back from the output, just in case
            //the surrogate decided to do something funky. There is also the simple
            //possibility that we couldn't create an instance of the object beforehand
            //so we are actually passing in 'null'.
            obj = surrogate.SetObjectData(obj,
                                          info,
                                          new StreamingContext(StreamingContextStates.File, context),
                                          this);

            if (SerializerBase.IsReferenceNull(obj))
            {
                Debug.LogWarning("The surrogate '" + surrogate.ToString() + "' could not create an instance of '" + objType.Name + "' for the element '" + firstChild.ParentNode.Name + "'.");
            }
            CacheObject(obj, objId);
            return(obj);
        }
예제 #2
0
        /// <summary>
        /// Main workhorse of the deserilizer. It processes primitives and recursively breaks
        /// complex types down into smaller primitives to be processed.
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        public object DeserializeCore(XmlElement element, object ownerObj = null, object standin = null)
        {
            // check if this is a reference to another object
            int    objId;
            string s = element.GetAttribute("id");

            if (int.TryParse(s, out objId))
            {
                object objCached = GetObjFromCache(objId);
                if (objCached != null)
                {
                    return(objCached);
                }
            }
            else
            {
                //TODO: If this is a defered object then we can't deserialize it just yet anyway
                objId = -1;
            }

            // check for null
            string value = element.GetAttribute("value");

            if (value == "null")
            {
                return(null);
            }

            int     subItems   = element.ChildNodes.Count;
            XmlNode firstChild = element.FirstChild;

            // load type cache if available
            if (element.GetAttribute("hasTypeCache") == "true")
            {
                LoadTypeCache((XmlElement)firstChild);
                subItems--;
                firstChild = firstChild.NextSibling;
            }
            // get type
            Type   objType;
            string typeId = element.GetAttribute("typeid");

            if (string.IsNullOrEmpty(typeId))
            {
                // no type id so type information must be present
                objType = InferTypeFromElement(element);
            }
            else
            {
                // there is a type id present
                objType = deserializationTypeCache[Convert.ToInt32(typeId)];
            }

            if (objType == null)
            {
                //if there was an id but it's not in the cache yet, this probably means
                //a circular reference to an object currently being deserialized. We can't
                //do anything useful with this information right now so we'll have to
                //add it to the defered deserialization list.
                if (objId != -1)
                {
                    //UPDATE: Unused at the moment. Was original intended to proces
                    //Component.gameObject references that had no type info

                    // the component surrogate doesn't add the 'defered' attribute so we need to do that now.
                    element.SetAttribute("defered", "true");
                    CheckForDeferedDeserialization(ownerObj, element.Name, element);

                    return(null);
                }

                //otherwise, something really screwy happened during serialization.
                Debug.LogWarning("No type info supplied for " + element.Name + ". Assigning null value.");
                return(null);
            }

            // our value
            object obj = standin;

            //Before we get crazy with built-in deserailizers we want to look at our
            //surrogates and see if any of them handle this datatype.
            ISurrogateSelector temp;
            var surrogate = this.GetSurrogate(objType, new StreamingContext(StreamingContextStates.File), out temp);

            if (surrogate != null)
            {
                obj = DeserializeSurrogate(surrogate, objType, objId, firstChild, element, standin);
                CacheObject(obj, objId);
                if (!SerializerBase.IsReferenceNull(obj))
                {
                    return(obj);
                }
            }

            // process enum
            if (objType.IsEnum)
            {
                long val = Convert.ToInt64(value, cult);
                return(Enum.ToObject(objType, val));
            }

            // process some simple types
            switch (Type.GetTypeCode(objType))
            {
            case TypeCode.Boolean: return(Convert.ToBoolean(value, cult));

            case TypeCode.Byte: return(Convert.ToByte(value, cult));

            case TypeCode.Char: return(Convert.ToChar(value, cult));

            case TypeCode.DBNull: return(DBNull.Value);

            case TypeCode.DateTime: return(Convert.ToDateTime(value, cult));

            case TypeCode.Decimal: return(Convert.ToDecimal(value, cult));

            case TypeCode.Double: return(Convert.ToDouble(value, cult));

            case TypeCode.Int16: return(Convert.ToInt16(value, cult));

            case TypeCode.Int32: return(Convert.ToInt32(value, cult));

            case TypeCode.Int64: return(Convert.ToInt64(value, cult));

            case TypeCode.SByte: return(Convert.ToSByte(value, cult));

            case TypeCode.Single: return(Convert.ToSingle(value, cult));

            case TypeCode.String: return(value);

            case TypeCode.UInt16: return(Convert.ToUInt16(value, cult));

            case TypeCode.UInt32: return(Convert.ToUInt32(value, cult));

            case TypeCode.UInt64: return(Convert.ToUInt64(value, cult));
            }

            //deserialize array
            if (objType.IsArray)
            {
                //we need to check the attributes to see if we have a multi-dimensional array
                string ranks = element.GetAttribute("Ranks");
                if (!string.IsNullOrEmpty(ranks))
                {
                    return(DeserializeMultiDimensionalArray(objType, objId, subItems, ranks, firstChild));
                }
                return(DeserializeArray(objType, objId, subItems, firstChild));
            }

            //last chance attempt to instantiate the object
            if (SerializerBase.IsReferenceNull(obj) && standin == null)
            {
                obj = CreateInstanceOfType(objType);
            }

            //we still have nothing. Just return null. We can't instatiate this object.
            if (SerializerBase.IsReferenceNull(obj))
            {
                return(null);
            }

            //can deserialize self
            IXmlSerializable xmlSer = obj as IXmlSerializable;

            if (xmlSer != null)
            {
                DeserializeSelf(xmlSer, element);
                return(obj);
            }

            //it's a list object
            IList lst = obj as IList;

            if (lst != null)
            {
                return(DeserializeIList(lst, firstChild));
            }

            //it's a dictionary object
            IDictionary dict = obj as IDictionary;

            if (dict != null)
            {
                return(DeserializeIDictionary(dict, firstChild));
            }

            //it's a dictionary entry (key/value pair)
            if (objType == typeof(DictionaryEntry) ||
                (objType.IsGenericType &&
                 objType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)))
            {
                return(DeserializeDictionaryEntry(element, firstChild));
            }

            //it's a regular class or struct
            DeserializeComplexType(obj, objType, firstChild);
            CacheObject(obj, objId);
            return(obj);
        }