+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
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);
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);
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)
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)
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;
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 {
+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.
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
{
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