예제 #1
0
        void INanoSerializable.Deserialize(IDataAdapter data, ISubDeserializer subDeserializer)
        {
            A = data.GetStringValue("1", true);

            object b = null;

            subDeserializer.ContinueDeserialization(typeof(object), data.GetChild("1").GetChild("2"), ref b);
            B = b;
        }
예제 #2
0
        /// <summary>
        /// Deserialize object from source data.
        /// </summary>
        /// <typeparam name="T">Type of the class to deserialize root. Use <see cref="object"/> if class is unknown.</typeparam>
        /// <param name="data">Data source to deserialize from</param>
        /// <returns>The object or root of object model deserialized from <paramref name="data"/>.</returns>
        /// <exception cref="SerializationException">thrown when deserialization fails</exception>
        public T DeserializeObject <T>(IDataAdapter data)
        {
            maxObjId = 1;
            objectCache.Clear();
            flags = (OptimizationFlags)data.GetIntValue(ATTRIBUTE_FLAGS, true);

            IDataAdapter types = data.GetChild(ELEMENT_TYPES);

            if (types != null)
            {
                IDataArray array = types.GetArray();
                int        index = 1;
                foreach (IDataAdapter child in array.GetChildren())
                {
                    typeCache.Add(index++, InternalResolveTypes(child.GetStringValue()));
                }
            }

            return((T)DeserializeObject(typeof(T), data, null));
        }
예제 #3
0
        private void FillObject(TypeWrapper wrapper, object target, IDataAdapter data)
        {
            if (wrapper.IsSelfSerializable)
            {
                ((INanoSerializable)target).Deserialize(data, this);
                return;
            }

            // read properties
            for (int i = 0; i < wrapper.Properties.Count; i++)
            {
                PropertyWrapper property = wrapper.Properties[i];

                // should be already loaded at this time
                if (property.ConstructorArg != -1 && property.State != NanoState.SerializeSet)
                {
                    continue;
                }

                if (property.Info.GetMethod.IsPrivate && property.Info.SetMethod.IsPrivate &&
                    (flags & OptimizationFlags.PrivateProperties) == 0)
                {
                    continue;
                }

                if (property.TypeCategory == TypeCategory.Primitive ||
                    property.TypeCategory == TypeCategory.Enum)
                {
                    if (!property.Info.CanWrite)
                    {
                        continue;
                    }

                    property.SetValue(
                        target,
                        DeserializePrimitive(
                            property.MemberType,
                            data,
                            property.Name,
                            property.Location != NanoLocation.SubNode,
                            (flags & OptimizationFlags.EnumAsValue) != 0
                            )
                        );
                }
                else
                {
                    IDataAdapter subnode = data.GetChild(property.Name);
                    if (subnode != null)
                    {
                        object currentValue = property.GetValue(target);
                        if (currentValue == null)
                        {
                            property.SetValue(target, DeserializeObject(property.MemberType, subnode, null));
                        }
                        else
                        {
                            DeserializeObject(property.MemberType, subnode, currentValue);
                        }
                    }
                }
            }

            // read fields
            for (int i = 0; i < wrapper.Fields.Count; i++)
            {
                FieldWrapper field = wrapper.Fields[i];

                // should be already loaded at this time
                if (field.ConstructorArg != -1 && field.State != NanoState.SerializeSet)
                {
                    continue;
                }

                if (field.TypeCategory == TypeCategory.Primitive ||
                    field.TypeCategory == TypeCategory.Enum)
                {
                    field.SetValue(
                        target,
                        DeserializePrimitive(
                            field.MemberType,
                            data,
                            field.Name,
                            field.Location != NanoLocation.SubNode,
                            (flags & OptimizationFlags.EnumAsValue) != 0
                            )
                        );
                }
                else
                {
                    IDataAdapter subnode = data.GetChild(field.Name);
                    if (subnode != null)
                    {
                        object value = DeserializeObject(field.MemberType, subnode, null);
                        if (value != null)
                        {
                            field.SetValue(target, value);
                        }
                    }
                }
            }
        }
예제 #4
0
        private object DeserializeObject(Type type, IDataAdapter data, object target)
        {
            // existing object
            TypeCategory category;

            if (target != null)
            {
                type = target.GetType();
                if ((flags & OptimizationFlags.NoContainers) == 0)
                {
                    category = GetTypeCategory(type);
                    if (category != TypeCategory.Unknown)
                    {
                        DeserializeContainer(type, category, data, ref target);
                        return(target);
                    }
                }

                FillObject(TypeCache.GetWrapper(type), target, data);
                return(target);
            }

            // resolve reference, if any
            if (type.IsClass && (flags & OptimizationFlags.NoReferences) == 0)
            {
                int id = (int)data.GetIntValue(ATTRIBUTE_OBJID, true);
                if (id > 0)
                {
                    return(objectCache[id]);
                }
            }

            // fix type, if needed
            int typeId = (int)data.GetIntValue(ATTRIBUTE_TYPE, true);

            if (typeId > 0)
            {
                if (!typeCache.TryGetValue(typeId, out type))
                {
                    throw new SerializationException($"Unable to find type {typeId}");
                }
            }

            // primitive type?
            if (IsPrimitive(type))
            {
                return(DeserializePrimitive(type, data, (flags & OptimizationFlags.EnumAsValue) != 0));
            }

            if ((flags & OptimizationFlags.NoContainers) == 0)
            {
                // load container
                category = GetTypeCategory(type);
                if (category != TypeCategory.Unknown)
                {
                    DeserializeContainer(type, category, data, ref target);

                    if ((flags & OptimizationFlags.NoReferences) == 0)
                    {
                        objectCache.Add(maxObjId++, target);
                    }
                    return(target);
                }
            }

            // this is unknown object
            TypeWrapper wrapper = TypeCache.GetWrapper(type);

            if (wrapper.Serializer != null)
            {
                return(wrapper.Serializer.DeserializeObject(data, this));
            }

            object[] constructorArgs = null;

            for (int i = 0; i < wrapper.Properties.Count; i++)
            {
                PropertyWrapper property = wrapper.Properties[i];
                if (property.ConstructorArg == -1)
                {
                    continue;
                }

                object value = null;
                if (property.TypeCategory == TypeCategory.Primitive ||
                    property.TypeCategory == TypeCategory.Enum)
                {
                    value = DeserializePrimitive(
                        property.MemberType,
                        data,
                        property.Name,
                        property.Location != NanoLocation.SubNode,
                        (flags & OptimizationFlags.EnumAsValue) != 0
                        );
                }
                else
                {
                    IDataAdapter subnode = data.GetChild(property.Name);
                    if (subnode != null)
                    {
                        value = DeserializeObject(property.MemberType, subnode, null);
                    }
                }

                if (constructorArgs == null)
                {
                    constructorArgs = new object[wrapper.ConstructorArgsCount];
                }
                constructorArgs[property.ConstructorArg] = value;
            }

            for (int i = 0; i < wrapper.Fields.Count; i++)
            {
                FieldWrapper field = wrapper.Fields[i];
                if (field.ConstructorArg == -1)
                {
                    continue;
                }

                object value = null;
                if (field.TypeCategory == TypeCategory.Primitive ||
                    field.TypeCategory == TypeCategory.Enum)
                {
                    value = DeserializePrimitive(
                        field.MemberType,
                        data,
                        field.Name,
                        field.Location != NanoLocation.SubNode,
                        (flags & OptimizationFlags.EnumAsValue) != 0
                        );
                }
                else
                {
                    IDataAdapter subnode = data.GetChild(field.Name);
                    if (subnode != null)
                    {
                        value = DeserializeObject(field.MemberType, subnode, null);
                    }
                }

                if (constructorArgs == null)
                {
                    constructorArgs = new object[wrapper.ConstructorArgsCount];
                }
                constructorArgs[field.ConstructorArg] = value;
            }

            // create object
            target = CreateObject(wrapper, constructorArgs);
            if ((flags & OptimizationFlags.NoReferences) == 0)
            {
                objectCache[maxObjId++] = target;
            }

            FillObject(wrapper, target, data);

            return(target);
        }