Contract-based type must ensure that the base type is also contract-based.
[mono.git] / mcs / class / System.Runtime.Serialization / System.Runtime.Serialization / KnownTypeCollection.cs
old mode 100644 (file)
new mode 100755 (executable)
index d85a917..66fb3c5
@@ -386,7 +386,7 @@ namespace System.Runtime.Serialization
 
                protected override void InsertItem (int index, Type type)
                {
-                       if (TryRegister (type))
+                       if (!Contains (type) && TryRegister (type))
                                base.InsertItem (index, type);
                }
 
@@ -407,21 +407,15 @@ namespace System.Runtime.Serialization
 
                protected override void SetItem (int index, Type type)
                {
-                       if (index == Count)
-                               InsertItem (index, type);
-                       else {
+                       if (index != Count)
                                RemoveItem (index);
-                               if (TryRegister (type))
-                                       base.InsertItem (index - 1, type);
-                       }
+                       if (TryRegister (type))
+                               base.InsertItem (index - 1, type);
                }
 
                internal SerializationMap FindUserMap (QName qname)
                {
-                       for (int i = 0; i < contracts.Count; i++)
-                               if (qname == contracts [i].XmlName)
-                                       return contracts [i];
-                       return null;
+                       return contracts.FirstOrDefault (c => c.XmlName == qname);
                }
 
                internal Type GetSerializedType (Type type)
@@ -566,6 +560,22 @@ namespace System.Runtime.Serialization
 
                static QName GetSerializableQName (Type type)
                {
+#if !NET_2_1
+                       // First, check XmlSchemaProviderAttribute and try GetSchema() to see if it returns a schema in the expected format.
+                       var xpa = type.GetCustomAttribute<XmlSchemaProviderAttribute> (true);
+                       if (xpa != null) {
+                               var mi = type.GetMethod (xpa.MethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+                               if (mi != null) {
+                                       try {
+                                               var xss = new XmlSchemaSet ();
+                                               return (XmlQualifiedName) mi.Invoke (null, new object [] {xss});
+                                       } catch {
+                                               // ignore.
+                                       }
+                               }
+                       }
+#endif
+
                        string xmlName = type.Name;
                        if (type.IsGenericType) {
                                xmlName = xmlName.Substring (0, xmlName.IndexOf ('`')) + "Of";
@@ -782,6 +792,12 @@ namespace System.Runtime.Serialization
                        contracts.Add (ret);
                        ret.Initialize ();
 
+                       if (type.BaseType != typeof (object)) {
+                               TryRegister (type.BaseType);
+                               if (!FindUserMap (type.BaseType).IsContractAllowedType)
+                                       throw new InvalidDataContractException (String.Format ("To be serializable by data contract, type '{0}' cannot inherit from non-contract and non-Serializable type '{1}'", type, type.BaseType));
+                       }
+
                        object [] attrs = type.GetCustomAttributes (typeof (KnownTypeAttribute), true);
                        for (int i = 0; i < attrs.Length; i++) {
                                KnownTypeAttribute kt = (KnownTypeAttribute) attrs [i];
@@ -795,6 +811,7 @@ namespace System.Runtime.Serialization
                {
                        DefaultTypeMap ret = new DefaultTypeMap (type, this);
                        contracts.Add (ret);
+                       ret.Initialize ();
                        return ret;
                }