[System] Fixes UdpClient.Receive with IPv6 endpoint
[mono.git] / mcs / class / System.ServiceModel.Web / System.Runtime.Serialization.Json / TypeMap.cs
index 67aaf7db84e340a787fe08dac6fcd88c6dc0e0bb..8378a70c220dcf9f7cba75b9347ccb19a6e91d31 100644 (file)
@@ -33,6 +33,7 @@ using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Reflection;
+using System.Runtime.CompilerServices;
 using System.Runtime.Serialization;
 using System.Text;
 using System.Xml;
@@ -85,7 +86,7 @@ namespace System.Runtime.Serialization.Json
                                if (!fi.IsStatic)
                                        l.Add (new TypeMapField (fi, null));
                        foreach (var pi in type.GetProperties ())
-                               if (pi.CanRead && pi.CanWrite && !pi.GetGetMethod ().IsStatic && pi.GetIndexParameters ().Length == 0)
+                               if (pi.CanRead && pi.CanWrite && !pi.GetGetMethod (true).IsStatic && pi.GetIndexParameters ().Length == 0)
                                        l.Add (new TypeMapProperty (pi, null));
                        l.Sort ((x, y) => x.Order != y.Order ? x.Order - y.Order : String.Compare (x.Name, y.Name, StringComparison.Ordinal));
                        return new TypeMap (type, null, l.ToArray ());
@@ -93,18 +94,40 @@ namespace System.Runtime.Serialization.Json
 
                internal static bool IsDictionary (Type type)
                {
-                       if (type.GetInterface ("System.Collections.IDictionary", false) != null)
+                       Type inter;
+                       inter = type.GetInterface ("System.Collections.IDictionary", false);
+                       if (inter != null
+                               && type.GetMethod ("Add", new Type[] { typeof (object), typeof (object) }) != null)
                                return true;
-                       if (type.GetInterface ("System.Collections.Generic.IDictionary`2", false) != null)
+                       
+                       inter = type.GetInterface ("System.Collections.Generic.IDictionary`2", false);
+                       if (inter != null
+                               && type.GetMethod ("Add", new Type[] { inter.GetGenericArguments() [0], 
+                                                                          inter.GetGenericArguments() [1] }) != null)
                                return true;
                        return false;
                }
 
-               internal static bool IsCollection (Type type)
+               internal static bool IsEnumerable (Type type)
                {
+                       if (type.IsGenericType && 
+                               type.GetGenericTypeDefinition() == typeof (LinkedList<>))
+                               return true;
+                       
                        if (IsPrimitiveType (type) || IsDictionary (type))
                                return false;
-                       if (type.GetInterface ("System.Collections.IEnumerable", false) != null)
+                       
+                       Type inter;
+                       inter = type.GetInterface ("System.Collections.Generic.IReadOnlyCollection`1", false);
+                       if (inter != null)
+                               return true;
+                       
+                       inter = type.GetInterface ("System.Collections.IEnumerable", false);
+                       if (inter != null && type.GetMethod ("Add", new Type[] { typeof (object) }) != null)
+                               return true;
+                       
+                       inter = type.GetInterface ("System.Collections.Generic.IEnumerable`1", false);
+                       if (inter != null && type.GetMethod ("Add", new Type[] { inter.GetGenericArguments() [0] }) != null)
                                return true;
                        return false;
                }
@@ -116,7 +139,9 @@ namespace System.Runtime.Serialization.Json
 
                        List<TypeMapMember> members = new List<TypeMapMember> ();
 
-                       foreach (FieldInfo fi in type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
+                       foreach (FieldInfo fi in type.GetFields (binding_flags)) {
+                               if (fi.GetCustomAttributes (typeof (CompilerGeneratedAttribute), false).Length > 0)
+                                       continue;
                                if (dca != null) {
                                        object [] atts = fi.GetCustomAttributes (typeof (DataMemberAttribute), true);
                                        if (atts.Length == 0)
@@ -131,13 +156,13 @@ namespace System.Runtime.Serialization.Json
                        }
 
                        if (dca != null) {
-                               foreach (PropertyInfo pi in type.GetProperties (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
+                               foreach (PropertyInfo pi in type.GetProperties (binding_flags)) {
                                        object [] atts = pi.GetCustomAttributes (typeof (DataMemberAttribute), true);
                                        if (atts.Length == 0)
                                                continue;
                                        if (pi.GetIndexParameters ().Length > 0)
                                                continue;
-                                       if (IsCollection (pi.PropertyType)) {
+                                       if (IsEnumerable (pi.PropertyType) || IsDictionary (pi.PropertyType)) {
                                                if (!pi.CanRead)
                                                        throw new InvalidDataContractException (String.Format ("Property {0} must have a getter", pi));
                                        }
@@ -207,7 +232,7 @@ namespace System.Runtime.Serialization.Json
                                        return Activator.CreateInstance (typeof (Dictionary<,>).MakeGenericType (type.GetGenericArguments ()));
                                else
                                        return new Hashtable ();
-                       } else if (TypeMap.IsCollection (type)) {
+                       } else if (TypeMap.IsEnumerable (type)) {
                                if (type.IsGenericType)
                                        return Activator.CreateInstance (typeof (List<>).MakeGenericType (type.GetGenericArguments ()));
                                else
@@ -217,7 +242,7 @@ namespace System.Runtime.Serialization.Json
                                return FormatterServices.GetUninitializedObject (type);
                }
 
-               public virtual object Deserialize (JsonSerializationReader jsr)
+               public virtual object Deserialize (JsonSerializationReader jsr, object o)
                {
                        XmlReader reader = jsr.Reader;
                        bool isNull = reader.GetAttribute ("type") == "null";
@@ -235,7 +260,7 @@ namespace System.Runtime.Serialization.Json
                                        if (mm.Name == reader.LocalName && reader.NamespaceURI == String.Empty) {
                                                if (filled.ContainsKey (mm))
                                                        throw new SerializationException (String.Format ("Object content '{0}' for '{1}' already appeared in the reader", reader.LocalName, type));
-                                               mm.SetMemberValue (ret, jsr.ReadObject (mm.Type));
+                                               mm.SetMemberValue (ret, jsr);
                                                filled [mm] = true;
                                                consumed = true;
                                                break;
@@ -282,7 +307,7 @@ namespace System.Runtime.Serialization.Json
 
                public abstract object GetMemberOf (object owner);
 
-               public abstract void SetMemberValue (object owner, object value);
+               public abstract void SetMemberValue (object owner, JsonSerializationReader value);
        }
 
        class TypeMapField : TypeMapMember
@@ -303,10 +328,10 @@ namespace System.Runtime.Serialization.Json
                {
                        return field.GetValue (owner);
                }
-
-               public override void SetMemberValue (object owner, object value)
+               
+               public override void SetMemberValue (object owner, JsonSerializationReader jsr)
                {
-                       field.SetValue (owner, value);
+                       field.SetValue (owner, jsr.ReadObject (this.Type));
                }
        }
 
@@ -329,9 +354,21 @@ namespace System.Runtime.Serialization.Json
                        return property.GetValue (owner, null);
                }
 
-               public override void SetMemberValue (object owner, object value)
+               public override void SetMemberValue (object owner, JsonSerializationReader jsr)
                {
-                       property.SetValue (owner, value, null);
+                       var pSetter = this.property.GetSetMethod (true);
+                       if (pSetter != null) {
+                               property.SetValue (owner, jsr.ReadObject (this.Type), null);
+                               
+                       } else { // no setter
+                               var oldValue = property.GetValue (owner, null);
+                               try {
+                                       jsr.ReadObject (this.Type, oldValue);
+                               } catch (MissingMethodException e) {
+                                       throw new InvalidDataContractException (string.Format ("No set method for property '{0}' "
+                                               + "in type '{1}'.", this.property.Name, this.property.PropertyType.FullName), e);
+                               }
+                       }
                }
        }
 }