2010-05-31 Atsushi Enomoto <atsushi@ximian.com>
authorAtsushi Eno <atsushieno@gmail.com>
Mon, 31 May 2010 10:32:30 +0000 (10:32 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Mon, 31 May 2010 10:32:30 +0000 (10:32 -0000)
* SerializationMap.cs, KnownTypeCollection.cs : contract namespace
  should be still considered even if contract (local) name is null.
  Fix crash for generic derived type of dictionary. Fixed the
  primary (crasher) part of bug #610036.

* XmlObjectSerializerTest.cs : add test for bug #610036.

svn path=/trunk/mcs/; revision=158197

mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/ChangeLog
mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/KnownTypeCollection.cs
mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/SerializationMap.cs
mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/ChangeLog
mcs/class/System.Runtime.Serialization/Test/System.Runtime.Serialization/XmlObjectSerializerTest.cs

index bb9c0f30c2c8e40cb56e80319a4368d1559497bd..1d1951318614ec596fefc737936a82359e74fda1 100755 (executable)
@@ -1,3 +1,10 @@
+2010-05-31  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * SerializationMap.cs, KnownTypeCollection.cs : contract namespace
+         should be still considered even if contract (local) name is null.
+         Fix crash for generic derived type of dictionary. Fixed the
+         primary (crasher) part of bug #610036.
+
 2010-05-19  Atsushi Enomoto  <atsushi@ximian.com>
 
        * XmlFormatterDeserializer.cs : Array of something with non-default
index c6501cacaef9b6081d45f99e6999d2247948cadb..d85a91774efad1ba0e3a6b7cf1b8bc07e491f212 100644 (file)
@@ -485,7 +485,7 @@ namespace System.Runtime.Serialization
                        return GetContractQName (type, null, null);
                }
 
-               static QName GetContractQName (Type type)
+               internal static QName GetContractQName (Type type)
                {
                        var a = GetAttribute<DataContractAttribute> (type);
                        return a == null ? null : GetContractQName (type, a.Name, a.Namespace);
@@ -499,16 +499,8 @@ namespace System.Runtime.Serialization
 
                static QName GetContractQName (Type type, string name, string ns)
                {
-                       if (name == null) {
-                               // FIXME: there could be decent ways to get 
-                               // the same result...
-                               name = type.Namespace == null || type.Namespace.Length == 0 ? type.Name : type.FullName.Substring (type.Namespace.Length + 1).Replace ('+', '.');
-                               if (type.IsGenericType) {
-                                       name = name.Substring (0, name.IndexOf ('`')) + "Of";
-                                       foreach (var t in type.GetGenericArguments ())
-                                               name += t.Name; // FIXME: check namespaces too
-                               }
-                       }
+                       if (name == null)
+                               name = GetDefaultName (type);
                        if (ns == null)
                                ns = GetDefaultNamespace (type);
                        return new QName (name, ns);
@@ -537,7 +529,20 @@ namespace System.Runtime.Serialization
                        return new QName (name, ns);
                }
 
-               static string GetDefaultNamespace (Type type)
+               internal static string GetDefaultName (Type type)
+               {
+                       // FIXME: there could be decent ways to get 
+                       // the same result...
+                       string name = type.Namespace == null || type.Namespace.Length == 0 ? type.Name : type.FullName.Substring (type.Namespace.Length + 1).Replace ('+', '.');
+                       if (type.IsGenericType) {
+                               name = name.Substring (0, name.IndexOf ('`')) + "Of";
+                               foreach (var t in type.GetGenericArguments ())
+                                       name += t.Name; // FIXME: check namespaces too
+                       }
+                       return name;
+               }
+
+               internal static string GetDefaultNamespace (Type type)
                {
                        foreach (ContractNamespaceAttribute a in type.Assembly.GetCustomAttributes (typeof (ContractNamespaceAttribute), true))
                                if (a.ClrNamespace == type.Namespace)
@@ -602,16 +607,16 @@ namespace System.Runtime.Serialization
                        if (RegisterEnum (type) != null)
                                return true;
 
-                       if (RegisterContract (type) != null)
+                       if (RegisterDictionary (type) != null)
                                return true;
 
-                       if (RegisterIXmlSerializable (type) != null)
+                       if (RegisterCollectionContract (type) != null)
                                return true;
 
-                       if (RegisterDictionary (type) != null)
+                       if (RegisterContract (type) != null)
                                return true;
 
-                       if (RegisterCollectionContract (type) != null)
+                       if (RegisterIXmlSerializable (type) != null)
                                return true;
 
                        if (RegisterCollection (type) != null)
index 28328ea5dae3d253bbed4d4dbb43b23955f7559c..b38e2ec3cfba63a3f9fee0703b2797a941e8c53f 100644 (file)
@@ -775,7 +775,7 @@ namespace System.Runtime.Serialization
        internal partial class DictionaryTypeMap : SerializationMap, ICollectionTypeMap
        {
                Type key_type, value_type;
-               QName dict_qname, item_qname, key_qname, value_qname;
+               QName item_qname, key_qname, value_qname;
                MethodInfo add_method;
                CollectionDataContractAttribute a;
 
@@ -825,35 +825,48 @@ namespace System.Runtime.Serialization
                public Type KeyType { get { return key_type; } }
                public Type ValueType { get { return value_type; } }
 
-               static readonly QName kvpair_key_qname = new QName ("Key", KnownTypeCollection.MSArraysNamespace);
-               static readonly QName kvpair_value_qname = new QName ("Value", KnownTypeCollection.MSArraysNamespace);
-
                internal virtual QName GetDictionaryQName ()
                {
-                       if (a != null && !String.IsNullOrEmpty (a.Name))
-                               return new QName (a.Name, ContractNamespace);
-                       return new QName ("ArrayOf" + GetItemQName ().Name, KnownTypeCollection.MSArraysNamespace);
+                       string name = a != null ? a.Name : null;
+                       string ns = a != null ? a.Namespace : null;
+                       if (RuntimeType.IsGenericType && RuntimeType.GetGenericTypeDefinition () != typeof (Dictionary<,>))
+                               name = name ?? KnownTypeCollection.GetDefaultName (RuntimeType);
+                       else
+                               name = "ArrayOf" + GetItemQName ().Name;
+                       ns = ns ?? KnownTypeCollection.MSArraysNamespace;
+
+                       return new QName (name, ns);
                }
 
                internal virtual QName GetItemQName ()
                {
-                       if (a != null && !String.IsNullOrEmpty (a.ItemName))
-                               return new QName (a.ItemName, ContractNamespace);
-                       return new QName ("KeyValueOf" + KnownTypes.GetQName (key_type).Name + KnownTypes.GetQName (value_type).Name, KnownTypeCollection.MSArraysNamespace);
+                       string name = a != null ? a.ItemName : null;
+                       string ns = a != null ? a.Namespace : null;
+
+                       name = name ?? "KeyValueOf" + KnownTypes.GetQName (key_type).Name + KnownTypes.GetQName (value_type).Name;
+                       ns = ns ?? (a != null ? ContractNamespace : KnownTypeCollection.MSArraysNamespace);
+
+                       return new QName (name, ns);
                }
 
                internal virtual QName GetKeyQName ()
                {
-                       if (a != null && !String.IsNullOrEmpty (a.KeyName))
-                               return new QName (a.KeyName, ContractNamespace);
-                       return kvpair_key_qname;
+                       string name = a != null ? a.KeyName : null;
+                       string ns = a != null ? a.Namespace : null;
+
+                       name = name ?? "Key";
+                       ns = ns ?? (a != null ? ContractNamespace : KnownTypeCollection.MSArraysNamespace);
+                       return new QName (name, ns);
                }
 
                internal virtual QName GetValueQName ()
                {
-                       if (a != null && !String.IsNullOrEmpty (a.ValueName))
-                               return new QName (a.ValueName, ContractNamespace);
-                       return kvpair_value_qname;
+                       string name = a != null ? a.ValueName : null;
+                       string ns = a != null ? a.Namespace : null;
+
+                       name = name ?? "Value";
+                       ns = ns ?? (a != null ? ContractNamespace : KnownTypeCollection.MSArraysNamespace);
+                       return new QName (name, ns);
                }
 
                internal virtual string CurrentNamespace {
index f3394f5bf4352d7863d658b09473150ed64e98ce..61c30a06f45e4f3d921be4b9cbc03dbfd75aa4be 100644 (file)
@@ -1,3 +1,7 @@
+2010-05-31  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * XmlObjectSerializerTest.cs : add test for bug #610036.
+
 2010-04-28  Atsushi Enomoto  <atsushi@ximian.com>
 
        * XmlObjectSerializerTest.cs : add test for bug #599899.
index 49abbf5ae1a0211397984be5afb17a0a93aa6192..a348430caa7ea1e198810ff3e60d761cd34491c4 100644 (file)
@@ -1387,8 +1387,42 @@ namespace MonoTests.System.Runtime.Serialization
                                ds.WriteObject (xw, person);
                        Assert.AreEqual (xml, sw.ToString ().Replace ('"', '\''), "#1");
                }
-       }
 
+               [Test]
+               public void Bug610036 ()
+               {
+                       var ms = new MemoryStream ();
+                       Type [] knownTypes = new Type [] { typeof (ParentClass), typeof (Foo), typeof (Bar) };
+
+                       var ds = new DataContractSerializer (typeof (Root), "Root", "Company.Foo", knownTypes, 1000, false, true, null);
+
+                       var root = new Root ("root");
+                       var bar1 = new Bar ("bar1");
+                       var bar2 = new Bar ("bar2");
+                       var bar3 = new Bar ("bar3");
+                       
+                       var foo1 = new Foo ("foo1");
+                       var foo2 = new Foo ("foo2");
+                       
+                       foo1.FDict.Add (bar1);
+                       foo1.FDict.Add (bar2);
+                       
+                       foo2.FDict.Add (bar1);
+                       foo2.FDict.Add (bar3);
+                       
+                       root.FDict.Add (foo1);
+                       root.FDict.Add (foo2);
+
+                       ds.WriteObject (ms, root);
+                       Console.WriteLine (Encoding.UTF8.GetString (ms.ToArray ()));
+                       ms.Position = 0;
+
+                       root = (Root) ds.ReadObject (ms);
+
+                       Assert.AreEqual (2, root.FDict.Count, "#1");
+               }
+       }
+       
        [DataContract]
        public class MemberIgnored
        {
@@ -1789,3 +1823,78 @@ namespace U2U.DataContracts
                public string Description { get; set; }
        }
 }
+
+#region bug #610036
+//parent class with a name property
+[DataContract (Namespace = "Company.Foo")]
+public abstract class ParentClass
+{
+       
+       //constructor
+       public ParentClass (string name)
+       {
+               Name = name;
+       }
+       
+       //the name
+       [DataMember]
+       public string Name{ get; set; }
+
+}
+
+//root object
+[DataContract (Namespace = "Company.Foo")]
+public class Root : ParentClass
+{
+       //dict
+       [DataMember]
+       public Dict<Foo> FDict; 
+       
+       //constructor
+       public Root (string name)
+               : base (name)
+       {
+               FDict = new Dict<Foo> ();
+       }
+}
+
+
+//subclass
+[DataContract (Namespace = "Company.Foo")]
+public class Foo : ParentClass
+{
+       //here is one dict
+       [DataMember]
+       public Dict<Bar> FDict;
+       
+       //constructor
+       public Foo (string name) 
+               : base (name)
+       {
+               FDict = new Dict<Bar> ();
+       }
+       
+}
+
+//another sublass
+[DataContract (Namespace = "Company.Foo")]
+public class Bar : ParentClass
+{
+       //constructor
+       public Bar (string name)
+               : base (name)
+       {
+       }
+       
+}
+//the custom dictionary
+[CollectionDataContract (ItemName = "DictItem", Namespace = "Company.Foo")]
+public class Dict<T> : Dictionary<string, T> where T : ParentClass
+{
+       public void Add (T item)
+       {
+               Add (item.Name, item);
+       }
+       
+}
+#endregion