Exemplo n.º 1
0
        /// <summary>
        /// Fills existing object with deserialized data.
        /// </summary>
        /// <typeparam name="T">Target type of the object</typeparam>
        /// <param name="target">Target object to fill</param>
        /// <param name="data">Data source to deserialize from</param>
        public void FillObject <T>(T target, IDataAdapter data)
        {
            maxObjId = 1;
            objectCache.Clear();
            flags = (OptimizationFlags)data.GetIntValue(ATTRIBUTE_FLAGS, true);

            TypeWrapper wrapper = TypeCache.GetWrapper(typeof(T));

            FillObject(wrapper, target, data);
        }
Exemplo n.º 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));
        }
Exemplo n.º 3
0
        protected static object DeserializePrimitive(Type type, IDataAdapter data, string name, bool isAttribute, bool enumAsValue)
        {
            Func <IDataAdapter, string, bool, object> func;

            if (primitiveNamedDeserializers.TryGetValue(type, out func))
            {
                return(func(data, name, isAttribute));
            }

            if (type.IsEnum)
            {
                if (enumAsValue)
                {
                    return(Enum.ToObject(type, data.GetIntValue(name, isAttribute)));
                }

                return(Enum.Parse(type, data.GetStringValue(name, isAttribute)));
            }

            return(null);
        }
Exemplo n.º 4
0
        private void DeserializeContainer(Type type, TypeCategory category, IDataAdapter data, ref object target)
        {
            // arrays
            if (category == TypeCategory.Array)
            {
                Type elementType = type.GetElementType();
                int  rank        = (int)data.GetIntValue(ATTRIBUTE_ARRAY_RANK, true);
                if (rank == 0)
                {
                    rank = 1;
                }

                int[] lengths = new int[rank];
                ScanArrayRanks(data, elementType, lengths, 0);

                Array array;
                if (target == null)
                {
                    target = array = Array.CreateInstance(elementType, lengths);
                }
                else
                {
                    array = (Array)target;
                }

                int[] coords = new int[array.Rank];
                DeserializeArrayRank(array, elementType, coords, 0, data);

                return;
            }

            // non generic containers
            switch (category)
            {
            case TypeCategory.IList:
                DeserializeContainer(ref target, type, typeof(object), data, "Add");
                return;

            case TypeCategory.Queue:
                DeserializeContainer(ref target, type, typeof(object), data, "Enqueue");
                return;

            case TypeCategory.Stack:
                DeserializeContainer(ref target, type, typeof(object), data, "Push", true);
                return;
            }

            // generics
            Type[] genericArgs = TypeCache.GetTypeGenericArgs(type);

            switch (category)
            {
            case TypeCategory.GenericIList:
                DeserializeContainer(ref target, type, genericArgs[0], data, "Add");
                return;

            case TypeCategory.GenericQueue:
                DeserializeContainer(ref target, type, genericArgs[0], data, "Enqueue");
                return;

            case TypeCategory.GenericStack:
                DeserializeContainer(ref target, type, genericArgs[0], data, "Push", true);
                return;

            case TypeCategory.ISet:
                DeserializeContainer(ref target, type, genericArgs[0], typeof(bool), data, "Add");
                return;

            case TypeCategory.LinkedList:
                DeserializeContainer(ref target, type, genericArgs[0], typeof(LinkedListNode <>).MakeGenericType(genericArgs[0]), data, "AddLast");
                return;
            }

            if (category == TypeCategory.IDictionary)
            {
                if (target == null)
                {
                    target = TypeCache.CreateParameterless(type);
                }

                Action <object, object, object> setAction = null;
                if (!TypeCache.TryGetTypeAccessor(type, ref setAction))
                {
                    setAction = InvocationHelper.CreateSetDelegate(type, genericArgs[0], genericArgs[1], "Add");
                    TypeCache.AddTypeAccessor(type, setAction);
                }

                foreach (IDataAdapter element in data.GetArray().GetChildren())
                {
                    setAction(
                        target,
                        DeserializeObject(genericArgs[0], element.GetChild("Key"), null),
                        DeserializeObject(genericArgs[1], element.GetChild("Value"), null)
                        );
                }
            }
        }
Exemplo n.º 5
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);
        }