Пример #1
0
        public object ReadObject(Type type)
        {
            if (serialized_object_count++ == serializer.MaxItemsInObjectGraph)
            {
                throw SerializationError(String.Format("The object graph exceeded the maximum object count '{0}' specified in the serializer", serializer.MaxItemsInObjectGraph));
            }

            bool nullable = false;

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                nullable = true;
                type     = Nullable.GetUnderlyingType(type);
            }

            bool isNull = reader.GetAttribute("type") == "null";

            switch (Type.GetTypeCode(type))
            {
            case TypeCode.DBNull:
                string dbn = reader.ReadElementContentAsString();
                if (dbn != String.Empty)
                {
                    throw new SerializationException(String.Format("The only expected DBNull value string is '{{}}'. Tha actual input was '{0}'.", dbn));
                }
                return(DBNull.Value);

            case TypeCode.String:
                if (isNull)
                {
                    reader.ReadElementContentAsString();
                    return(null);
                }
                else
                {
                    return(reader.ReadElementContentAsString());
                }

            case TypeCode.Char:
                var c = reader.ReadElementContentAsString();
                if (c.Length > 1)
                {
                    throw new XmlException("Invalid JSON char");
                }
                return(Char.Parse(c));

            case TypeCode.Single:
            case TypeCode.Double:
            case TypeCode.Decimal:
                return(ReadValueType(type, nullable));

            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.Int64:
                if (type.IsEnum)
                {
                    return(Enum.ToObject(type, Convert.ChangeType(reader.ReadElementContentAsLong(), Enum.GetUnderlyingType(type), null)));
                }
                else
                {
                    return(ReadValueType(type, nullable));
                }

            case TypeCode.UInt64:
                if (type.IsEnum)
                {
                    return(Enum.ToObject(type, Convert.ChangeType(reader.ReadElementContentAsDecimal(), Enum.GetUnderlyingType(type), null)));
                }
                else
                {
                    return(ReadValueType(type, nullable));
                }

            case TypeCode.Boolean:
                return(ReadValueType(type, nullable));

            case TypeCode.DateTime:
                // it does not use ReadElementContentAsDateTime(). Different string format.
                var s = reader.ReadElementContentAsString();
                if (s.Length < 2 || !s.StartsWith("/Date(", StringComparison.Ordinal) || !s.EndsWith(")/", StringComparison.Ordinal))
                {
                    if (nullable)
                    {
                        return(null);
                    }
                    throw new XmlException("Invalid JSON DateTime format. The value format should be '/Date(UnixTime)/'");
                }

                // The date can contain [SIGN]LONG, [SIGN]LONG+HOURSMINUTES or [SIGN]LONG-HOURSMINUTES
                // the format for HOURSMINUTES is DDDD
                int tidx = s.IndexOf('-', 8);
                if (tidx == -1)
                {
                    tidx = s.IndexOf('+', 8);
                }
                int minutes = 0;
                if (tidx == -1)
                {
                    s = s.Substring(6, s.Length - 8);
                }
                else
                {
                    int offset;
                    int.TryParse(s.Substring(tidx + 1, s.Length - 3 - tidx), out offset);

                    minutes = (offset % 100) + (offset / 100) * 60;
                    if (s [tidx] == '-')
                    {
                        minutes = -minutes;
                    }

                    s = s.Substring(6, tidx - 6);
                }
                var date = new DateTime(1970, 1, 1).AddMilliseconds(long.Parse(s));
                if (minutes != 0)
                {
                    date = date.AddMinutes(minutes);
                }
                return(date);

            default:
                if (type == typeof(Guid))
                {
                    return(new Guid(reader.ReadElementContentAsString()));
                }
                else if (type == typeof(Uri))
                {
                    if (isNull)
                    {
                        reader.ReadElementContentAsString();
                        return(null);
                    }
                    else
                    {
                        return(new Uri(reader.ReadElementContentAsString(), UriKind.RelativeOrAbsolute));
                    }
                }
                else if (type == typeof(XmlQualifiedName))
                {
                    s = reader.ReadElementContentAsString();
                    int idx = s.IndexOf(':');
                    return(idx < 0 ? new XmlQualifiedName(s) : new XmlQualifiedName(s.Substring(0, idx), s.Substring(idx + 1)));
                }
                else if (type != typeof(object))
                {
                    // strongly-typed object
                    if (reader.IsEmptyElement)
                    {
                        // empty -> null array or object
                        reader.Read();
                        return(null);
                    }

                    Type ct = GetCollectionElementType(type);
                    if (ct != null)
                    {
                        return(DeserializeGenericCollection(type, ct));
                    }
                    else
                    {
                        TypeMap map = GetTypeMap(type);
                        return(map.Deserialize(this));
                    }
                }
                else
                {
                    return(ReadInstanceDrivenObject());
                }
            }
        }
Пример #2
0
        object DeserializeGenericCollection(Type collectionType, Type elementType, object collectionInstance)
        {
            reader.ReadStartElement();
            object ret;

            if (collectionType.IsInterface)
            {
                collectionType = typeof(List <>).MakeGenericType(elementType);
            }
            if (TypeMap.IsDictionary(collectionType))
            {
                if (collectionInstance == null)
                {
                    collectionInstance = Activator.CreateInstance(collectionType);
                }

                var        keyType   = elementType.IsGenericType ? elementType.GetGenericArguments() [0] : typeof(object);
                var        valueType = elementType.IsGenericType ? elementType.GetGenericArguments() [1] : typeof(object);
                MethodInfo add       = collectionType.GetMethod("Add", new Type [] { keyType, valueType });

                for (reader.MoveToContent(); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent())
                {
                    if (!reader.IsStartElement("item"))
                    {
                        throw SerializationError(String.Format("Expected element 'item', but found '{0}' in namespace '{1}'", reader.LocalName, reader.NamespaceURI));
                    }

                    // reading a KeyValuePair in the form of <Key .../><Value .../>
                    reader.Read();
                    reader.MoveToContent();
                    object key = ReadObject(keyType);
                    reader.MoveToContent();
                    object val = ReadObject(valueType);
                    reader.Read();
                    add.Invoke(collectionInstance, new [] { key, val });
                }
                ret = collectionInstance;
            }
            else if (typeof(IList).IsAssignableFrom(collectionType))
            {
#if NET_2_1
                Type listType = collectionType.IsArray ? typeof(List <>).MakeGenericType(elementType) : null;
#else
                Type listType = collectionType.IsArray ? typeof(ArrayList) : null;
#endif

                IList c;
                if (collectionInstance == null)
                {
                    c = (IList)Activator.CreateInstance(listType ?? collectionType);
                }
                else
                {
                    c = (IList)collectionInstance;
                }

                for (reader.MoveToContent(); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent())
                {
                    if (!reader.IsStartElement("item"))
                    {
                        throw SerializationError(String.Format("Expected element 'item', but found '{0}' in namespace '{1}'", reader.LocalName, reader.NamespaceURI));
                    }
                    Type   et   = elementType == typeof(object) || elementType.IsAbstract ? null : elementType;
                    object elem = ReadObject(et ?? typeof(object));
                    c.Add(elem);
                }
#if NET_2_1
                if (collectionType.IsArray)
                {
                    Array array = Array.CreateInstance(elementType, c.Count);
                    c.CopyTo(array, 0);
                    ret = array;
                }
                else
                {
                    ret = c;
                }
#else
                ret = collectionType.IsArray ? ((ArrayList)c).ToArray(elementType) : c;
#endif
            }
            else
            {
                if (collectionInstance == null)
                {
                    collectionInstance = Activator.CreateInstance(collectionType);
                }

                MethodInfo add;
                if (collectionInstance.GetType().IsGenericType&&
                    collectionInstance.GetType().GetGenericTypeDefinition() == typeof(LinkedList <>))
                {
                    add = collectionType.GetMethod("AddLast", new Type [] { elementType });
                }
                else
                {
                    add = collectionType.GetMethod("Add", new Type [] { elementType });
                }

                if (add == null)
                {
                    var icoll = typeof(ICollection <>).MakeGenericType(elementType);
                    if (icoll.IsAssignableFrom(collectionInstance.GetType()))
                    {
                        add = icoll.GetMethod("Add");
                    }
                }
                if (add == null)
                {
                    throw new MissingMethodException(elementType.FullName, "Add");
                }

                for (reader.MoveToContent(); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent())
                {
                    if (!reader.IsStartElement("item"))
                    {
                        throw SerializationError(String.Format("Expected element 'item', but found '{0}' in namespace '{1}'", reader.LocalName, reader.NamespaceURI));
                    }
                    object element = ReadObject(elementType);
                    add.Invoke(collectionInstance, new object [] { element });
                }
                ret = collectionInstance;
            }

            reader.ReadEndElement();
            return(ret);
        }
Пример #3
0
        object DeserializeGenericCollection(Type collectionType, Type elementType)
        {
            reader.ReadStartElement();
            object ret;

            if (collectionType.IsInterface)
            {
                collectionType = typeof(List <>).MakeGenericType(elementType);
            }
            if (TypeMap.IsDictionary(collectionType))
            {
                object dic        = Activator.CreateInstance(collectionType);
                var    itemSetter = dic.GetType().GetProperty("Item");
                var    keyarr     = new object [1];

                for (reader.MoveToContent(); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent())
                {
                    if (!reader.IsStartElement("item"))
                    {
                        throw SerializationError(String.Format("Expected element 'item', but found '{0}' in namespace '{1}'", reader.LocalName, reader.NamespaceURI));
                    }

                    // reading a KeyValuePair in the form of <Key .../><Value .../>
                    reader.Read();
                    reader.MoveToContent();
                    object key = ReadObject(elementType.GetGenericArguments() [0]);
                    reader.MoveToContent();
                    object val = ReadObject(elementType.GetGenericArguments() [1]);
                    reader.Read();
                    keyarr [0] = key;
                    itemSetter.SetValue(dic, val, keyarr);
                }
                ret = dic;
            }
            else if (typeof(IList).IsAssignableFrom(collectionType))
            {
#if NET_2_1
                Type listType = collectionType.IsArray ? typeof(List <>).MakeGenericType(elementType) : null;
#else
                Type listType = collectionType.IsArray ? typeof(ArrayList) : null;
#endif
                IList c = (IList)Activator.CreateInstance(listType ?? collectionType);
                for (reader.MoveToContent(); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent())
                {
                    if (!reader.IsStartElement("item"))
                    {
                        throw SerializationError(String.Format("Expected element 'item', but found '{0}' in namespace '{1}'", reader.LocalName, reader.NamespaceURI));
                    }
                    Type   et   = elementType == typeof(object) || elementType.IsAbstract ? null : elementType;
                    object elem = ReadObject(et ?? typeof(object));
                    c.Add(elem);
                }
#if NET_2_1
                if (collectionType.IsArray)
                {
                    Array array = Array.CreateInstance(elementType, c.Count);
                    c.CopyTo(array, 0);
                    ret = array;
                }
                else
                {
                    ret = c;
                }
#else
                ret = collectionType.IsArray ? ((ArrayList)c).ToArray(elementType) : c;
#endif
            }
            else
            {
                object     c   = Activator.CreateInstance(collectionType);
                MethodInfo add = collectionType.GetMethod("Add", new Type [] { elementType });
                if (add == null)
                {
                    var icoll = typeof(ICollection <>).MakeGenericType(elementType);
                    if (icoll.IsAssignableFrom(c.GetType()))
                    {
                        add = icoll.GetMethod("Add");
                    }
                }

                for (reader.MoveToContent(); reader.NodeType != XmlNodeType.EndElement; reader.MoveToContent())
                {
                    if (!reader.IsStartElement("item"))
                    {
                        throw SerializationError(String.Format("Expected element 'item', but found '{0}' in namespace '{1}'", reader.LocalName, reader.NamespaceURI));
                    }
                    object elem = ReadObject(elementType);
                    add.Invoke(c, new object [] { elem });
                }
                ret = c;
            }

            reader.ReadEndElement();
            return(ret);
        }
Пример #4
0
        public void WriteObjectContent(object graph, bool top, bool outputTypeName)
        {
            if (graph == null)
            {
                if (top)
                {
                    GetTypeMap(root_type);                      // to make sure to reject invalid contracts
                }
                writer.WriteString(null);
                return;
            }

            if (serialized_object_count++ == serializer.MaxItemsInObjectGraph)
            {
                throw new SerializationException(String.Format("The object graph exceeded the maximum object count '{0}' specified in the serializer", serializer.MaxItemsInObjectGraph));
            }

            switch (Type.GetTypeCode(graph.GetType()))
            {
            case TypeCode.Char:
            case TypeCode.String:
                writer.WriteString(graph.ToString());
                break;

            case TypeCode.Single:
            case TypeCode.Double:
                writer.WriteAttributeString("type", "number");
                writer.WriteString(((IFormattable)graph).ToString("R", CultureInfo.InvariantCulture));
                break;

            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
            case TypeCode.Decimal:
                writer.WriteAttributeString("type", "number");
                if (graph.GetType().IsEnum)
                {
                    graph = ((IConvertible)graph).ToType(Enum.GetUnderlyingType(graph.GetType()), CultureInfo.InvariantCulture);
                }
                writer.WriteString(((IFormattable)graph).ToString("G", CultureInfo.InvariantCulture));
                break;

            case TypeCode.Boolean:
                writer.WriteAttributeString("type", "boolean");
                if ((bool)graph)
                {
                    writer.WriteString("true");
                }
                else
                {
                    writer.WriteString("false");
                }
                break;

            case TypeCode.DateTime:
                writer.WriteString(String.Format(CultureInfo.InvariantCulture, "/Date({0})/", (long)((DateTime)graph).Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds));
                break;

            default:
                if (graph is Guid)
                {
                    goto case TypeCode.String;
                }
                else if (graph is Uri)
                {
                    goto case TypeCode.String;
                }
                else if (graph is XmlQualifiedName)
                {
                    XmlQualifiedName qn = (XmlQualifiedName)graph;
                    writer.WriteString(qn.Name);
                    writer.WriteString(":");
                    writer.WriteString(qn.Namespace);
                }
                else if (graph is IDictionary)
                {
                    writer.WriteAttributeString("type", "array");
                    IDictionary dic = (IDictionary)graph;
                    foreach (object o in dic.Keys)
                    {
                        writer.WriteStartElement("item");
                        writer.WriteAttributeString("type", "object");
                        // outputting a KeyValuePair as <Key .. /><Value ... />
                        writer.WriteStartElement("Key");
                        WriteObjectContent(o, false, !(graph is Array && graph.GetType().GetElementType() != typeof(object)));
                        writer.WriteEndElement();
                        writer.WriteStartElement("Value");
                        WriteObjectContent(dic[o], false, !(graph is Array && graph.GetType().GetElementType() != typeof(object)));
                        writer.WriteEndElement();
                        writer.WriteEndElement();
                    }
                }
                else if (graph is ICollection)                     // array
                {
                    writer.WriteAttributeString("type", "array");
                    foreach (object o in (ICollection)graph)
                    {
                        writer.WriteStartElement("item");
                        // when it is typed, then no need to output "__type"
                        WriteObjectContent(o, false, !(graph is Array && graph.GetType().GetElementType() != typeof(object)));
                        writer.WriteEndElement();
                    }
                }
                else                     // object
                {
                    TypeMap tm = GetTypeMap(graph.GetType());
                    if (tm != null)
                    {
                        // FIXME: I'm not sure how it is determined whether __type is written or not...
                        if (outputTypeName || always_emit_type)
                        {
                            writer.WriteAttributeString("__type", FormatTypeName(graph.GetType()));
                        }
                        tm.Serialize(this, graph, "object");
                    }
                    else
                    {
                        // it does not emit type="object" (as the graph is regarded as a string)
//						writer.WriteString (graph.ToString ());
                        throw new InvalidDataContractException(String.Format("Type {0} cannot be serialized by this JSON serializer", graph.GetType()));
                    }
                }
                break;
            }
        }