2007-09-25 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlTypeMapping.cs
index d0e35adfc4875172fcc6e693d0b93ca41a546230..bbf222f03dedf699f51a4fe4f789df2f78966b55 100644 (file)
@@ -34,6 +34,7 @@ using System;
 using System.Collections;
 using System.Globalization;
 using System.Xml.Schema;
+using System.Reflection;
 
 namespace System.Xml.Serialization
 {
@@ -101,11 +102,13 @@ namespace System.Xml.Serialization
                internal string XmlType
                {
                        get { return xmlType; }
+                       set { xmlType = value; }
                }
 
                internal string XmlTypeNamespace
                {
                        get { return xmlTypeNamespace; }
+                       set { xmlTypeNamespace = value; }
                }
 
                internal ArrayList DerivedTypes
@@ -150,17 +153,16 @@ namespace System.Xml.Serialization
                        set { isNullable = value; }
                }
 
-               internal XmlTypeMapping GetRealTypeMap (string objectFullTypeName)
+               internal XmlTypeMapping GetRealTypeMap (Type objectType)
                {
                        if (TypeData.SchemaType == SchemaTypes.Enum)
                                return this;
 
                        // Returns the map for a subtype of this map's type
-                       objectFullTypeName = objectFullTypeName.Replace ('+','.');
-                       if (TypeFullName == objectFullTypeName) return this;
+                       if (TypeData.Type == objectType) return this;
                        for (int n=0; n<_derivedTypes.Count; n++) {
                                XmlTypeMapping map = (XmlTypeMapping) _derivedTypes[n];
-                               if (map.TypeFullName == objectFullTypeName) return map;
+                               if (map.TypeData.Type == objectType) return map;
                        }
                        
                        return null;
@@ -189,11 +191,60 @@ namespace System.Xml.Serialization
        internal class XmlSerializableMapping : XmlTypeMapping
        {
                XmlSchema _schema;
+#if NET_2_0
+               XmlSchemaComplexType _schemaType;
+               XmlQualifiedName _schemaTypeName;
+#endif
 
                internal XmlSerializableMapping(string elementName, string ns, TypeData typeData, string xmlType, string xmlTypeNamespace)
                        : base(elementName, ns, typeData, xmlType, xmlTypeNamespace)
                {
-                       IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance(typeData.Type);
+#if NET_2_0
+                       XmlSchemaProviderAttribute schemaProvider = (XmlSchemaProviderAttribute) Attribute.GetCustomAttribute (typeData.Type, typeof (XmlSchemaProviderAttribute));
+
+                       if (schemaProvider != null) {
+                               string method = schemaProvider.MethodName;
+                               MethodInfo mi = typeData.Type.GetMethod (method, BindingFlags.Static | BindingFlags.Public);
+                               if (mi == null)
+                                       throw new InvalidOperationException (String.Format ("Type '{0}' must implement public static method '{1}'", typeData.Type, method));
+                               if (!typeof (XmlQualifiedName).IsAssignableFrom (mi.ReturnType) &&
+                                   // LAMESPEC: it is undocumented. (We don't have to tell users about it in the error message.)
+                                   // Also do not add such a silly compatibility test to assert that it does not raise an error.
+                                   !typeof (XmlSchemaComplexType).IsAssignableFrom (mi.ReturnType))
+                                       throw new InvalidOperationException (String.Format ("Method '{0}' indicated by XmlSchemaProviderAttribute must have its return type as XmlQualifiedName", method));
+                               XmlSchemaSet xs = new XmlSchemaSet ();
+                               object retVal = mi.Invoke (null, new object [] { xs });
+                               _schemaTypeName = XmlQualifiedName.Empty;
+                               if (retVal == null)
+                                       return;
+
+                               if (retVal is XmlSchemaComplexType) {
+                                       _schemaType = (XmlSchemaComplexType) retVal;
+                                       if (!_schemaType.QualifiedName.IsEmpty)
+                                               _schemaTypeName = _schemaType.QualifiedName;
+                                       else
+                                               _schemaTypeName = new XmlQualifiedName (xmlType, xmlTypeNamespace);
+                               }
+                               else if (retVal is XmlQualifiedName) {
+                                       _schemaTypeName = (XmlQualifiedName)retVal;
+                               }
+                               else
+                                       throw new InvalidOperationException (
+                                               String.Format ("Method {0}.{1}() specified by XmlSchemaProviderAttribute has invalid signature: return type must be compatible with System.Xml.XmlQualifiedName.", typeData.Type.Name, method));
+
+                               XmlTypeNamespace = _schemaTypeName.Namespace;
+                               XmlType = _schemaTypeName.Name;
+
+                               if (!_schemaTypeName.IsEmpty && xs.Count > 0) {
+                                       XmlSchema [] schemas = new XmlSchema [xs.Count];
+                                       xs.CopyTo (schemas, 0);
+                                       _schema = schemas [0];
+                               }
+
+                               return;
+                       }
+#endif
+                       IXmlSerializable serializable = (IXmlSerializable)Activator.CreateInstance (typeData.Type, true);
                        _schema = serializable.GetSchema();
                        if (_schema != null) 
                        {
@@ -206,6 +257,16 @@ namespace System.Xml.Serialization
                {
                        get { return _schema; }
                }
+
+#if NET_2_0
+               internal XmlSchemaType SchemaType {
+                       get { return _schemaType; }
+               }
+
+               internal XmlQualifiedName SchemaTypeName {
+                       get { return _schemaTypeName; }
+               }
+#endif
        }