2005-07-29 Lluis Sanchez Gual <lluis@novell.com>
authorLluis Sanchez <lluis@novell.com>
Fri, 29 Jul 2005 10:02:06 +0000 (10:02 -0000)
committerLluis Sanchez <lluis@novell.com>
Fri, 29 Jul 2005 10:02:06 +0000 (10:02 -0000)
* SoapWriter.cs: Wrap method signature headers in a MethodSignature
object before serializing. Track changes in SoapTypeMapper.
* SoapReader.cs: Track changes in SoapTypeMapper. Factorized some code.
* SoapTypeMapper.cs: Replaced indexers by regular methods, this makes
code easier to read an understand. Simplified the code for registering
basic soap types. Added support for types from
System.Runtime.Remoting.Metadata.W3cXsd2001. Implemented support
for MethodSignature serialization. All this fixes bug #75537.

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

mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/ChangeLog
mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapReader.cs
mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapTypeMapper.cs
mcs/class/System.Runtime.Serialization.Formatters.Soap/System.Runtime.Serialization.Formatters.Soap/SoapWriter.cs

index 374d45989ad77c99f3811a0ec14e4f3e514d3822..58eb1b1e6a98ab7e42d348e6ff4160c55adc1d09 100644 (file)
@@ -1,3 +1,14 @@
+2005-07-29  Lluis Sanchez Gual <lluis@novell.com>
+
+       * SoapWriter.cs: Wrap method signature headers in a MethodSignature
+       object before serializing. Track changes in SoapTypeMapper.
+       * SoapReader.cs: Track changes in SoapTypeMapper. Factorized some code.
+       * SoapTypeMapper.cs: Replaced indexers by regular methods, this makes
+       code easier to read an understand. Simplified the code for registering
+       basic soap types. Added support for types from
+       System.Runtime.Remoting.Metadata.W3cXsd2001. Implemented support
+       for MethodSignature serialization. All this fixes bug #75537.
+
 2005-07-14  Lluis Sanchez Gual <lluis@novell.com>
 
        * SoapReader.cs: Fixed parsing of array dimensions. Patch by Roei Erez
index a899c1d5928ffc519f1965dd37809528bd894f1f..495191023ea8262100d2265992127010c927dd2f 100644 (file)
@@ -151,7 +151,15 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        return TopObject;\r
                }\r
                \r
-               #endregion\r
+               #endregion
+               
+               public SoapTypeMapper Mapper {
+                       get { return mapper; }
+               }
+               \r
+               public XmlTextReader XmlReader {
+                       get { return xmlReader; }
+               }\r
 \r
                #region Private Methods\r
 \r
@@ -193,18 +201,12 @@ namespace System.Runtime.Serialization.Formatters.Soap {
 \r
                private Type GetComponentType()\r
                {\r
-                       Type type = null;\r
-                       \r
                        string strValue = xmlReader["type", XmlSchema.InstanceNamespace];\r
                        if(strValue == null) {\r
                                if(GetId() != 0) return typeof(string);\r
                                return null;\r
                        }\r
-                       string[] strName = strValue.Split(':');\r
-                       string namespaceURI = xmlReader.LookupNamespace(strName[0]);\r
-                       type = mapper[new Element(string.Empty, strName[1], namespaceURI)];\r
-\r
-                       return type;\r
+                       return GetTypeFromQName (strValue);\r
                }\r
 \r
                private bool DeserializeMessage(ISoapMessage message) \r
@@ -360,7 +362,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        int[] indices = new int[numberOfDims];\r
 \r
                        // Create the array\r
-                       Type arrayType = mapper[new Element(arrayInfo[0], arrayElementType, xmlReader.LookupNamespace(arrayInfo[0]))];\r
+                       Type arrayType = mapper.GetType (arrayElementType, xmlReader.LookupNamespace(arrayInfo[0]));\r
                        Array array = Array.CreateInstance(\r
                                arrayType,\r
                                lengths);
@@ -435,13 +437,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                private object Deserialize()\r
                {\r
                        object objReturn = null;\r
-                       Element element = new Element(\r
-                               xmlReader.Prefix,\r
-                               xmlReader.LocalName,\r
-                               xmlReader.NamespaceURI);\r
-\r
-\r
-                       Type type = mapper[element];\r
+                       Type type = mapper.GetType (xmlReader.LocalName, xmlReader.NamespaceURI);\r
 \r
                        // Get the Id\r
                        long id = GetId();\r
@@ -472,10 +468,9 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        bool NeedsSerializationInfo = false;\r
                        bool hasFixup;\r
 \r
-                       if(SoapTypeMapper.CanBeValue(type)) \r
+                       if(mapper.IsInternalSoapType (type)) \r
                        {\r
-                               string elementString = xmlReader.ReadElementString();\r
-                               object obj = SoapTypeMapper.ParseXsdValue (elementString, type);\r
+                               object obj = mapper.ReadInternalSoapValue (this, type);\r
                                \r
                                if(id != 0) \r
                                        RegisterObject(id, obj, info, parentId, parentMemberInfo, indices);\r
@@ -750,6 +745,13 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        \r
                        _fieldIndices[type] = tm;\r
                        return tm;\r
+               }
+               
+               public Type GetTypeFromQName (string qname)
+               {
+                       string[] strName = qname.Split(':');\r
+                       string namespaceURI = xmlReader.LookupNamespace (strName[0]);\r
+                       return mapper.GetType (strName[1], namespaceURI);\r
                }\r
                \r
                #endregion\r
index 4efb5dea203c97fea4db5dd5110dc2f9183a5749..a30f0caccfa4c54490843f29df1151596ad5a4fa 100644 (file)
@@ -37,6 +37,7 @@ using System.Runtime.Serialization.Formatters;
 using System.Xml.Schema;
 using System.Runtime.Remoting.Metadata.W3cXsd2001;
 using System.Globalization;
+using System.Text;
 
 namespace System.Runtime.Serialization.Formatters.Soap {
 
@@ -45,6 +46,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                private string _prefix;
                private string _localName;
                private string _namespaceURI;
+               private MethodInfo _parseMethod;
 
                public Element(string prefix, string localName, string namespaceURI) 
                {
@@ -81,6 +83,11 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        }
                }
 
+               public MethodInfo ParseMethod {
+                       get { return _parseMethod; }
+                       set { _parseMethod = value; }
+               }
+
                public override bool Equals(object obj) 
                {
                        Element element = obj as Element;
@@ -101,7 +108,8 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                }
        }
 
-       internal class SoapTypeMapper {
+       internal class SoapTypeMapper
+       {
                private static Hashtable xmlNodeToTypeTable = new Hashtable();
                private static Hashtable typeToXmlNodeTable = new Hashtable();
                public static readonly string SoapEncodingNamespace = "http://schemas.xmlsoap.org/soap/encoding/";
@@ -163,245 +171,208 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        InitMappingTables();
                        
                }
-
-               public Type this[Element element]
+               
+               static string GetKey (string localName, string namespaceUri)
                {
-                       get 
-                       {
-                               Type type = null;
+                       return localName + " " +  namespaceUri;
+               }
+               
+/*             public Type this [Element element]
+               {
+               }
+*/
+               public Type GetType (string xmlName, string xmlNamespace)
+               {
+                       Type type = null;
 
-                               string localName = XmlConvert.DecodeName(element.LocalName);
-                               string namespaceURI = XmlConvert.DecodeName(element.NamespaceURI);
-                               string typeNamespace, assemblyName;
-                               SoapServices.DecodeXmlNamespaceForClrTypeNamespace(
-                                       element.NamespaceURI, 
-                                       out typeNamespace, 
-                                       out assemblyName);
-                               string typeName = typeNamespace + Type.Delimiter + localName;
+                       string localName = XmlConvert.DecodeName (xmlName);
+                       string namespaceURI = XmlConvert.DecodeName (xmlNamespace);
+                       string typeNamespace, assemblyName;
+                       
+                       SoapServices.DecodeXmlNamespaceForClrTypeNamespace(
+                               xmlNamespace, 
+                               out typeNamespace, 
+                               out assemblyName);
 
-                               if(assemblyName != null && assemblyName != string.Empty && _binder != null) 
-                               {
-                                       type = _binder.BindToType(assemblyName, typeName);
-                               }
-                               if(type == null) 
+                       string typeName = typeNamespace + Type.Delimiter + localName;
+
+                       if(assemblyName != null && assemblyName != string.Empty && _binder != null) 
+                       {
+                               type = _binder.BindToType(assemblyName, typeName);
+                       }
+                       if(type == null) 
+                       {
+                               string assemblyQualifiedName = (string)xmlNodeToTypeTable [GetKey (xmlName, xmlNamespace)];
+                               if(assemblyQualifiedName != null)
+                                       type = Type.GetType(assemblyQualifiedName);
+                               else
                                {
-                                       string assemblyQualifiedName = (string)xmlNodeToTypeTable[element];
-                                       if(assemblyQualifiedName != null)
-                                               type = Type.GetType(assemblyQualifiedName);
-                                       else
+                                       type = Type.GetType(xmlName);
+                                       if(type == null) 
                                        { 
 
-                                               type = Type.GetType(element.LocalName);
+                                               type = Type.GetType(typeName);
                                                if(type == null) 
-                                               { 
-
-                                                       type = Type.GetType(typeName);
-                                                       if(type == null) 
-                                                       {
-
-                                                               if(assemblyName == null || assemblyName == String.Empty)
-                                                                       throw new SerializationException(
-                                                                               String.Format("Parse Error, no assembly associated with XML key {0} {1}", 
-                                                                               localName, 
-                                                                               namespaceURI));
-                                                               type = FormatterServices.GetTypeFromAssembly(
-                                                                       Assembly.Load(assemblyName), 
-                                                                       typeName);
-                                                       }
+                                               {
+
+                                                       if(assemblyName == null || assemblyName == String.Empty)
+                                                               throw new SerializationException(
+                                                                       String.Format("Parse Error, no assembly associated with XML key {0} {1}", 
+                                                                       localName, 
+                                                                       namespaceURI));
+                                                       type = FormatterServices.GetTypeFromAssembly(
+                                                               Assembly.Load(assemblyName), 
+                                                               typeName);
                                                }
                                        }
-                                       if(type == null)
-                                               throw new SerializationException();
                                }
-                               return type;
+                               if(type == null)
+                                       throw new SerializationException();
                        }
+                       return type;
                }
 
-
-               public Element this[string typeFullName, string assemblyName]
+               public Element GetXmlElement (string typeFullName, string assemblyName)
                {
-                       get 
+                       Element element;
+                       string typeNamespace = string.Empty;
+                       string typeName = typeFullName;
+                       if(_assemblyFormat == FormatterAssemblyStyle.Simple)\r
+                       {
+                               string[] items = assemblyName.Split(',');
+                               assemblyName = items[0];
+                       }
+                       string assemblyQualifiedName = typeFullName + ", " + assemblyName;
+                       element = (Element) typeToXmlNodeTable[assemblyQualifiedName];
+                       if(element == null)
                        {
-                               Element element;
-                               string typeNamespace = string.Empty;
-                               string typeName = typeFullName;
-                               if(_assemblyFormat == FormatterAssemblyStyle.Simple)\r
+                               int typeNameIndex = typeFullName.LastIndexOf('.');
+                               if(typeNameIndex != -1) 
                                {
-                                       string[] items = assemblyName.Split(',');
-                                       assemblyName = items[0];
+                                       typeNamespace = typeFullName.Substring(0, typeNameIndex);
+                                       typeName = typeFullName.Substring(typeNamespace.Length + 1);
                                }
-                               string assemblyQualifiedName = typeFullName + ", " + assemblyName;
-                               element = (Element) typeToXmlNodeTable[assemblyQualifiedName];
-                               if(element == null)
+                               string namespaceURI = 
+                                       SoapServices.CodeXmlNamespaceForClrTypeNamespace(
+                                       typeNamespace, 
+                                       (!assemblyName.StartsWith("mscorlib"))?assemblyName:String.Empty);
+                               string prefix = (string) namespaceToPrefixTable[namespaceURI];
+                               if(prefix == null || prefix == string.Empty)
                                {
-                                       int typeNameIndex = typeFullName.LastIndexOf('.');
-                                       if(typeNameIndex != -1) 
-                                       {
-                                               typeNamespace = typeFullName.Substring(0, typeNameIndex);
-                                               typeName = typeFullName.Substring(typeNamespace.Length + 1);
-                                       }
-                                       string namespaceURI = 
-                                               SoapServices.CodeXmlNamespaceForClrTypeNamespace(
-                                               typeNamespace, 
-                                               (!assemblyName.StartsWith("mscorlib"))?assemblyName:String.Empty);
-                                       string prefix = (string) namespaceToPrefixTable[namespaceURI];
-                                       if(prefix == null || prefix == string.Empty)
-                                       {
-                                               prefix = "a" + (_prefixNumber++).ToString();
-                                               namespaceToPrefixTable[namespaceURI] = prefix;
+                                       prefix = "a" + (_prefixNumber++).ToString();
+                                       namespaceToPrefixTable[namespaceURI] = prefix;
 
-                                       }
-                                       int i = typeName.IndexOf ("[");
-                                       if (i != -1)
-                                               typeName = XmlConvert.EncodeName (typeName.Substring (0, i)) + typeName.Substring (i);
-                                       else
-                                               typeName = XmlConvert.EncodeName (typeName);
-                                       element = new Element(
-                                               prefix, 
-                                               typeName, 
-                                               namespaceURI);
                                }
-                               return element;
+                               int i = typeName.IndexOf ("[");
+                               if (i != -1)
+                                       typeName = XmlConvert.EncodeName (typeName.Substring (0, i)) + typeName.Substring (i);
+                               else
+                                       typeName = XmlConvert.EncodeName (typeName);
+                               element = new Element(
+                                       prefix, 
+                                       typeName, 
+                                       namespaceURI);
                        }
+                       return element;
                }
 
-               public Element this[Type type]
+               public Element GetXmlElement (Type type)
                {
-                       get 
+                       if(type == typeof(string)) return elementString;
+                       Element element = (Element) typeToXmlNodeTable[type.AssemblyQualifiedName];
+                       if(element == null)
                        {
-                               if(type == typeof(string)) return elementString;
-                               Element element = (Element) typeToXmlNodeTable[type.AssemblyQualifiedName];
-                               if(element == null)
-                               {
-                                       element = this[type.FullName, type.Assembly.FullName];
+                               element = GetXmlElement (type.FullName, type.Assembly.FullName);
 //                                     if(_assemblyFormat == FormatterAssemblyStyle.Full)
 //                                             element = this[type.FullName, type.Assembly.FullName];
 //                                     else
 //                                             element = this[type.FullName, type.Assembly.GetName().Name];
 
-                               }
-                               else
-                               {
-                                       element = new Element((element.Prefix == null)?_xmlWriter.LookupPrefix(element.NamespaceURI):element.Prefix, element.LocalName, element.NamespaceURI);
-                               }
-                               if(element == null)
-                                       throw new SerializationException("Oooops");
-                               return element;
                        }
+                       else if (_xmlWriter != null)
+                       {
+                               element = new Element((element.Prefix == null)?_xmlWriter.LookupPrefix(element.NamespaceURI):element.Prefix, element.LocalName, element.NamespaceURI);
+                       }
+                       if(element == null)
+                               throw new SerializationException("Oooops");
+                       return element;
                }
 
-               public static bool CanBeValue(Type type)
+               static void RegisterType (Type type, string name, string namspace)
                {
-                       if(type.IsPrimitive) return true;
-                       if(type.IsEnum) return true;
-                       if(_canBeValueTypeList.BinarySearch(type.ToString()) >= 0) 
-                       {
-                               return true;
-                       }
-                       return false;
+                       RegisterType (type, name, namspace, true);
+               }
+               
+               static Element RegisterType (Type type, string name, string namspace, bool reverseMap)
+               {
+                       Element element = new Element (name, namspace);
+                       xmlNodeToTypeTable.Add (GetKey (name, namspace), type.AssemblyQualifiedName);
+                       if (reverseMap)
+                               typeToXmlNodeTable.Add (type.AssemblyQualifiedName, element);
+                       return element;
+               }
+               
+               static void RegisterType (Type type)
+               {
+                       string name = (string) type.GetProperty ("XsdType", BindingFlags.Public | BindingFlags.Static).GetValue (null, null);
+                       Element element = RegisterType (type, name, XmlSchema.Namespace, true);
+                       element.ParseMethod = type.GetMethod ("Parse", BindingFlags.Public | BindingFlags.Static);
+                       if (element.ParseMethod == null)
+                               throw new InvalidOperationException ("Parse method not found in class " + type);
                }
 
                private static void InitMappingTables() 
                {
-                       Element element;
-                       Type elementType;
-                       element = new Element("Array", SoapEncodingNamespace);
-                       elementType = typeof(System.Array);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("string", XmlSchema.Namespace);
-                       elementType = typeof(string);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-//                     typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("string", SoapEncodingNamespace);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-
-                       element = new Element("boolean", XmlSchema.Namespace);
-                       elementType = typeof(bool);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("byte", XmlSchema.Namespace);
-                       elementType = typeof(sbyte);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("unsignedByte", XmlSchema.Namespace);
-                       elementType = typeof(byte);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("long", XmlSchema.Namespace);
-                       elementType = typeof(long);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("unsignedLong", XmlSchema.Namespace);
-                       elementType = typeof(ulong);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("int", XmlSchema.Namespace);
-                       elementType = typeof(int);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("unsignedInt", XmlSchema.Namespace);
-                       elementType = typeof(uint);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("float", XmlSchema.Namespace);
-                       elementType = typeof(float);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("double", XmlSchema.Namespace);
-                       elementType = typeof(double);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("decimal", XmlSchema.Namespace);
-                       elementType = typeof(decimal);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("short", XmlSchema.Namespace);
-                       elementType = typeof(short);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("unsignedShort", XmlSchema.Namespace);
-                       elementType = typeof(ushort);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("anyType", XmlSchema.Namespace);
-                       elementType = typeof(object);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("dateTime", XmlSchema.Namespace);
-                       elementType = typeof(DateTime);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("duration", XmlSchema.Namespace);
-                       elementType = typeof(TimeSpan);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("Fault", SoapEnvelopeNamespace);
-                       elementType = typeof(System.Runtime.Serialization.Formatters.SoapFault);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
-
-                       element = new Element("base64", SoapEncodingNamespace);
-                       elementType = typeof(byte[]);
-                       xmlNodeToTypeTable.Add(element, elementType.AssemblyQualifiedName);
-                       typeToXmlNodeTable.Add(elementType.AssemblyQualifiedName, element);
+                       RegisterType (typeof(System.Array), "Array", SoapEncodingNamespace);
+                       RegisterType (typeof(string), "string", XmlSchema.Namespace, false);
+                       RegisterType (typeof(string), "string", SoapEncodingNamespace, false);
+                       RegisterType (typeof(bool), "boolean", XmlSchema.Namespace);
+                       RegisterType (typeof(sbyte), "byte", XmlSchema.Namespace);
+                       RegisterType (typeof(byte), "unsignedByte", XmlSchema.Namespace);
+                       RegisterType (typeof(long), "long", XmlSchema.Namespace);
+                       RegisterType (typeof(ulong), "unsignedLong", XmlSchema.Namespace);
+                       RegisterType (typeof(int), "int", XmlSchema.Namespace);
+                       RegisterType (typeof(uint), "unsignedInt", XmlSchema.Namespace);
+                       RegisterType (typeof(float), "float", XmlSchema.Namespace);
+                       RegisterType (typeof(double), "double", XmlSchema.Namespace);
+                       RegisterType (typeof(decimal), "decimal", XmlSchema.Namespace);
+                       RegisterType (typeof(short), "short", XmlSchema.Namespace);
+                       RegisterType (typeof(ushort), "unsignedShort", XmlSchema.Namespace);
+                       RegisterType (typeof(object), "anyType", XmlSchema.Namespace);
+                       RegisterType (typeof(DateTime), "dateTime", XmlSchema.Namespace);
+                       RegisterType (typeof(TimeSpan), "duration", XmlSchema.Namespace);
+                       RegisterType (typeof(SoapFault), "Fault", SoapEnvelopeNamespace);
+                       RegisterType (typeof(byte[]), "base64", SoapEncodingNamespace);
+                       RegisterType (typeof(MethodSignature), "methodSignature", SoapEncodingNamespace);
+                       RegisterType (typeof(SoapAnyUri));
+                       RegisterType (typeof(SoapEntity));
+                       RegisterType (typeof(SoapMonth));
+                       RegisterType (typeof(SoapNonNegativeInteger));
+                       RegisterType (typeof(SoapToken));
+                       RegisterType (typeof(SoapBase64Binary));
+                       RegisterType (typeof(SoapHexBinary));
+                       RegisterType (typeof(SoapMonthDay));
+                       RegisterType (typeof(SoapNonPositiveInteger));
+                       RegisterType (typeof(SoapYear));
+                       RegisterType (typeof(SoapDate));
+                       RegisterType (typeof(SoapId));
+                       RegisterType (typeof(SoapName));
+                       RegisterType (typeof(SoapNormalizedString));
+                       RegisterType (typeof(SoapYearMonth));
+                       RegisterType (typeof(SoapIdref));
+                       RegisterType (typeof(SoapNcName));
+                       RegisterType (typeof(SoapNotation));
+                       RegisterType (typeof(SoapDay));
+                       RegisterType (typeof(SoapIdrefs));
+                       RegisterType (typeof(SoapNegativeInteger));
+                       RegisterType (typeof(SoapPositiveInteger));
+                       RegisterType (typeof(SoapInteger));
+                       RegisterType (typeof(SoapNmtoken));
+                       RegisterType (typeof(SoapQName));
+                       RegisterType (typeof(SoapEntities));
+                       RegisterType (typeof(SoapLanguage));
+                       RegisterType (typeof(SoapNmtokens));
+                       RegisterType (typeof(SoapTime));
                }
                
                public static string GetXsdValue (object value)
@@ -424,6 +395,9 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        else if (value is bool) {
                                return ((bool) value) ? "true" : "false";
                        }
+                       else if (value is MethodSignature) {
+                               return null;
+                       }
                        else {
                                return value.ToString ();
                        }
@@ -453,6 +427,99 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                                return Convert.ChangeType (value, type, CultureInfo.InvariantCulture);
                        }
                }
-
+               
+               public static bool CanBeValue (Type type)
+               {
+                       if(type.IsPrimitive) return true;
+                       if(type.IsEnum) return true;
+                       if(_canBeValueTypeList.BinarySearch(type.ToString()) >= 0) 
+                       {
+                               return true;
+                       }
+                       return false;
+               }
+               
+               public bool IsInternalSoapType (Type type)
+               {
+                       if (CanBeValue (type))
+                               return true;
+                       if (typeof(ISoapXsd).IsAssignableFrom (type))
+                               return true;
+                       if (type == typeof (MethodSignature))
+                               return true;
+                       return false;
+               }
+               
+               public object ReadInternalSoapValue (SoapReader reader, Type type)
+               {
+                       if (CanBeValue (type))
+                               return ParseXsdValue (reader.XmlReader.ReadElementString (), type);
+                       
+                       if (type == typeof(MethodSignature)) {
+                               return MethodSignature.ReadXmlValue (reader);
+                       }
+                       
+                       string val = reader.XmlReader.ReadElementString ();
+                       
+                       Element elem = GetXmlElement (type);
+                       if (elem.ParseMethod != null)
+                               return elem.ParseMethod.Invoke (null, new object[] { val });
+                       
+                       throw new SerializationException ("Can't parse type " + type);
+               }
+               
+               public string GetInternalSoapValue (SoapWriter writer, object value)
+               {
+                       if (CanBeValue (value.GetType()))
+                               return GetXsdValue (value);
+                       else if (value is MethodSignature)
+                               return ((MethodSignature)value).GetXmlValue (writer);
+                       else
+                               return value.ToString ();
+               }
+       }
+       
+       class MethodSignature
+       {
+               Type[] types;
+               
+               public MethodSignature (Type[] types)
+               {
+                       this.types = types;
+               }
+               
+               public static object ReadXmlValue (SoapReader reader)
+               {
+                       reader.XmlReader.MoveToElement ();
+                       if (reader.XmlReader.IsEmptyElement) {
+                               reader.XmlReader.Skip ();
+                               return null;
+                       }
+                       reader.XmlReader.ReadStartElement ();
+                       string names = reader.XmlReader.ReadString ();
+                       while (reader.XmlReader.NodeType != XmlNodeType.EndElement)
+                               reader.XmlReader.Skip ();
+                               
+                       ArrayList types = new ArrayList ();
+                       string[] tns = names.Split (' ');
+                       foreach (string tn in tns) {
+                               if (tn.Length == 0) continue;
+                               types.Add (reader.GetTypeFromQName (tn));
+                       }
+                       reader.XmlReader.ReadEndElement ();
+                       return (Type[]) types.ToArray (typeof(Type));
+               }
+               
+               public string GetXmlValue (SoapWriter writer)
+               {
+                       StringBuilder sb = new StringBuilder ();
+                       foreach (Type t in types) {
+                               Element elem = writer.Mapper.GetXmlElement (t);
+                               if (sb.Length > 0) sb.Append (' ');
+                               string prefix = writer.GetNamespacePrefix (elem);
+                               sb.Append (prefix).Append (':').Append (elem.LocalName);
+                       }
+                       return sb.ToString ();
+               }
        }
 }
index 6339addab7dbfdfa95b5db5239dfbb69a8c90806..42f3d28ff69f79b9fcfb1c06550dfe34973c2b8f 100644 (file)
@@ -110,7 +110,15 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        defaultMessageNamespace = typeof(SoapWriter).Assembly.GetName().FullName;\r
                }\r
 \r
-               #endregion\r
+               #endregion
+               
+               public SoapTypeMapper Mapper {
+                       get { return _mapper; }
+               }
+               \r
+               public XmlTextWriter XmlWriter {
+                       get { return _xmlWriter; }
+               }\r
 \r
                #region Internal Properties\r
 \r
@@ -314,8 +322,18 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        _xmlWriter.WriteStartElement ("h4", header.Name, ns);
                        if (header.MustUnderstand)
                                _xmlWriter.WriteAttributeString ("mustUnderstand", SoapTypeMapper.SoapEnvelopeNamespace, "1");\r
-                       _xmlWriter.WriteAttributeString ("root", SoapTypeMapper.SoapEncodingNamespace, "1");\r
-                       SerializeComponent (header.Value, true);\r
+                       _xmlWriter.WriteAttributeString ("root", SoapTypeMapper.SoapEncodingNamespace, "1");
+                       
+                       if (header.Name == "__MethodSignature") {
+                               // This is a lame way of identifying the signature header, but looks like it is
+                               // what MS.NET does.
+                               Type[] val = header.Value as Type[];
+                               if (val == null)
+                                       throw new SerializationException ("Invalid method signature.");
+                               SerializeComponent (new MethodSignature (val), true);
+                       } else
+                               SerializeComponent (header.Value, true);
+                               \r
                        _xmlWriter.WriteEndElement();\r
                }\r
 \r
@@ -367,7 +385,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        // with a id = 0\r
                        if(currentObjectId > 0)\r
                        {\r
-                               Element element = _mapper[currentType];\r
+                               Element element = _mapper.GetXmlElement (currentType);\r
                                _xmlWriter.WriteStartElement(element.Prefix, element.LocalName, element.NamespaceURI);\r
                                Id(currentObjectId);\r
                        }
@@ -420,7 +438,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        // Same as above\r
                        if(currentObjectId > 0L)\r
                        {\r
-                               Element element = _mapper[info.FullTypeName, info.AssemblyName];\r
+                               Element element = _mapper. GetXmlElement (info.FullTypeName, info.AssemblyName);\r
                                _xmlWriter.WriteStartElement(element.Prefix, element.LocalName, element.NamespaceURI);\r
                                Id(currentObjectId);\r
                        }\r
@@ -438,12 +456,12 @@ namespace System.Runtime.Serialization.Formatters.Soap {
 \r
                private void SerializeArray(Array currentArray, long currentArrayId) \r
                {\r
-                       Element element = _mapper[typeof(System.Array)];\r
+                       Element element = _mapper.GetXmlElement (typeof(System.Array));\r
                        \r
 \r
                        // Set the arrayType attribute\r
                        Type arrayType = currentArray.GetType().GetElementType();\r
-                       Element xmlArrayType = _mapper[arrayType];\r
+                       Element xmlArrayType = _mapper.GetXmlElement (arrayType);\r
                        _xmlWriter.WriteStartElement(element.Prefix, element.LocalName, element.NamespaceURI);\r
                        if(currentArrayId > 0) Id(currentArrayId);\r
                        \r
@@ -453,18 +471,11 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                                _xmlWriter.WriteFullEndElement();\r
                                return;\r
                        }\r
-\r
-                       if(_xmlWriter.LookupPrefix(xmlArrayType.NamespaceURI) == null)\r
-                       {\r
-                               _xmlWriter.WriteAttributeString(\r
-                                       "xmlns",\r
-                                       xmlArrayType.Prefix,\r
-                                       "http://www.w3.org/2000/xmlns/",\r
-                                       xmlArrayType.NamespaceURI);\r
-                       }\r
+
+                       string prefix = GetNamespacePrefix (xmlArrayType);\r
 \r
                        StringBuilder str = new StringBuilder();\r
-                       str.AppendFormat("{0}:{1}[",xmlArrayType.Prefix, xmlArrayType.LocalName);\r
+                       str.AppendFormat("{0}:{1}[", prefix, xmlArrayType.LocalName);\r
                        for(int i = 0; i < currentArray.Rank; i++)\r
                        {\r
                                str.AppendFormat("{0},", currentArray.GetUpperBound(i) + 1);\r
@@ -517,10 +528,10 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                                return;\r
                        }\r
                        Type objType = obj.GetType();\r
-                       bool canBeValue = SoapTypeMapper.CanBeValue(objType);\r
+                       bool canBeValue = _mapper.IsInternalSoapType (objType);\r
                        bool firstTime;\r
-                       long id = 0;\r
-\r
+                       long id = 0;
+                       
                        // An object already serialized\r
                        if((id = idGen.HasId(obj, out firstTime)) != 0L) \r
                        {\r
@@ -563,7 +574,7 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                                return;\r
                        }\r
 \r
-                       _xmlWriter.WriteString (SoapTypeMapper.GetXsdValue (obj));\r
+                       _xmlWriter.WriteString (_mapper.GetInternalSoapValue (this, obj));\r
                }\r
                \r
                private void EncodeType(Type type) \r
@@ -571,24 +582,30 @@ namespace System.Runtime.Serialization.Formatters.Soap {
                        if(type == null) \r
                                throw new SerializationException("Oooops");\r
 \r
-                       Element xmlType = _mapper[type];\r
-\r
-                       _xmlWriter.WriteAttributeString(\r
+                       Element xmlType = _mapper.GetXmlElement (type);\r
+
+                       string prefix = GetNamespacePrefix (xmlType);
+                       \r
+                       _xmlWriter.WriteAttributeString (\r
                                "xsi",\r
                                "type",\r
                                "http://www.w3.org/2001/XMLSchema-instance",\r
-                               xmlType.Prefix + ":" + xmlType.LocalName);\r
-                       string prefix = _xmlWriter.LookupPrefix(xmlType.NamespaceURI);\r
+                               prefix + ":" + xmlType.LocalName);
+               }
+               
+               public string GetNamespacePrefix (Element xmlType)
+               {
+                       string prefix = _xmlWriter.LookupPrefix (xmlType.NamespaceURI);\r
                        if(prefix == null || prefix == string.Empty) \r
                        {\r
                                _xmlWriter.WriteAttributeString(\r
                                        "xmlns",\r
                                        xmlType.Prefix,\r
                                        "http://www.w3.org/2000/xmlns/",\r
-                                       xmlType.NamespaceURI);\r
-\r
-                       }\r
-\r
+                                       xmlType.NamespaceURI);
+                               return xmlType.Prefix;\r
+                       }
+                       return prefix;\r
                }\r
        }\r
 }\r