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 isNull = reader.GetAttribute ("type") == "null";
+
switch (Type.GetTypeCode (type)) {
case TypeCode.DBNull:
string dbn = reader.ReadElementContentAsString ();
throw new SerializationException (String.Format ("The only expected DBNull value string is '{{}}'. Tha actual input was '{0}'.", dbn));
return DBNull.Value;
case TypeCode.String:
- return reader.ReadElementContentAsString ();
+ if (isNull) {
+ reader.ReadElementContentAsString ();
+ return null;
+ }
+ else
+ return reader.ReadElementContentAsString ();
case TypeCode.Single:
return reader.ReadElementContentAsFloat ();
case TypeCode.Double:
case TypeCode.UInt32:
int i = reader.ReadElementContentAsInt ();
if (type.IsEnum)
- return Enum.ToObject (type, i);
+ return Enum.ToObject (type, (object)i);
else
- return Convert.ChangeType (i, type);
+ return Convert.ChangeType (i, type, null);
case TypeCode.Int64:
case TypeCode.UInt64:
long l = reader.ReadElementContentAsLong ();
if (type.IsEnum)
- return Enum.ToObject (type, l);
+ return Enum.ToObject (type, (object)l);
else
- return Convert.ChangeType (l, type);
+ return Convert.ChangeType (l, type, null);
case TypeCode.Boolean:
return reader.ReadElementContentAsBoolean ();
+ 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))
+ throw new XmlException ("Invalid JSON DateTime format. The value format should be '/Date(UnixTime)/'");
+ return new DateTime (1970, 1, 1).AddMilliseconds (long.Parse (s.Substring (6, s.Length - 8)));
default:
if (type == typeof (Guid)) {
return new Guid (reader.ReadElementContentAsString ());
} else if (type == typeof (Uri)) {
- return new Uri (reader.ReadElementContentAsString ());
+ if (isNull) {
+ reader.ReadElementContentAsString ();
+ return null;
+ }
+ else
+ return new Uri (reader.ReadElementContentAsString ());
} else if (type == typeof (XmlQualifiedName)) {
- string s = reader.ReadElementContentAsString ();
+ 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)) {
foreach (Type t in serializer.KnownTypes)
if (t.FullName == name)
return t;
- return Type.GetType (name, false);
+ var ret = root_type.Assembly.GetType (name, false) ?? Type.GetType (name, false);
+ if (ret != null)
+ return ret;
+#if !NET_2_1 // how to do that in ML?
+ // We probably have to iterate all the existing
+ // assemblies that are loaded in current domain.
+ foreach (var ass in AppDomain.CurrentDomain.GetAssemblies ()) {
+ ret = ass.GetType (name, false);
+ if (ret != null)
+ return ret;
+ }
+#endif
+ return null;
}
object ReadInstanceDrivenObject ()
return type.GetElementType ();
if (type.IsGenericType) {
// returns T for ICollection<T>
- Type gt = type.GetGenericTypeDefinition ();
- if (gt == typeof (ICollection<>))
- return type.GetGenericArguments () [0];
+ Type [] ifaces = type.GetInterfaces ();
+ foreach (Type i in ifaces)
+ if (i.IsGenericType && i.GetGenericTypeDefinition ().Equals (typeof (ICollection<>)))
+ return i.GetGenericArguments () [0];
}
if (typeof (IList).IsAssignableFrom (type))
// return typeof(object) for mere collection.
{
reader.ReadStartElement ();
object ret;
+ if (collectionType.IsInterface)
+ collectionType = typeof (List<>).MakeGenericType (elementType);
if (typeof (IList).IsAssignableFrom (collectionType)) {
- IList c = collectionType.IsArray ?
- new ArrayList () :
- (IList) Activator.CreateInstance (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));
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));