* SoapReflectionImporter.cs: implemented.
authorLluis Sanchez <lluis@novell.com>
Thu, 5 Jun 2003 18:17:28 +0000 (18:17 -0000)
committerLluis Sanchez <lluis@novell.com>
Thu, 5 Jun 2003 18:17:28 +0000 (18:17 -0000)
* TypeTranslator.cs: added IsPrimitive() method
* TypeMapping.cs: Added RelatedMaps property that returns all maps directly or indirectly
  used by that one. Also added Format property, that can be literal or encoded.
* XmlReflectionImporter.cs: little fixes. Moved some methods to ReflectionHelper.
* XmlReflectionMember.cs: added constructor that accepts SoapAttributes
* XmlSerializationReader.cs: implemented many methods needed to support encoded format.
* XmlSerializationReaderInterpreter.cs: added support for encoded format.
* XmlSerializationWriter.cs: added support for encoded format.
* XmlSerializationWriterInterpreter.cs: added support for encoded format.
* XmlTypeMapElementInfo.cs: added some properties needed to support encoded format
* XmlTypeMapMemberAttribute.cs: added MappedType property (enum values can be attributes,
  and a map is needed for them).
* XmlTypeMapMemberElement.cs: small fixes.
* XmlTypeMapping.cs: added some properties and methods needed to support encoded format
* ReflectionHelper.cs: added. Has some methods shared by the reflection importers.

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

15 files changed:
mcs/class/System.XML/System.Xml.Serialization/ChangeLog
mcs/class/System.XML/System.Xml.Serialization/ReflectionHelper.cs [new file with mode: 0644]
mcs/class/System.XML/System.Xml.Serialization/SoapReflectionImporter.cs
mcs/class/System.XML/System.Xml.Serialization/TypeTranslator.cs
mcs/class/System.XML/System.Xml.Serialization/XmlMapping.cs
mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs
mcs/class/System.XML/System.Xml.Serialization/XmlReflectionMember.cs
mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs
mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs
mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriter.cs
mcs/class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs
mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapElementInfo.cs
mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMemberAttribute.cs
mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapMemberElement.cs
mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs

index 0fc51fe4597292ae5a794bdf1f1bb3ba55b4bc3c..5b0510424d5552f7d312611c37a4947d7bc4d493 100755 (executable)
@@ -1,3 +1,22 @@
+2003-06-05  Lluis Sanchez Gual <lluis@ximian.com>
+
+       * SoapReflectionImporter.cs: implemented.
+       * TypeTranslator.cs: added IsPrimitive() method
+       * TypeMapping.cs: Added RelatedMaps property that returns all maps directly or indirectly
+         used by that one. Also added Format property, that can be literal or encoded.
+       * XmlReflectionImporter.cs: little fixes. Moved some methods to ReflectionHelper.
+       * XmlReflectionMember.cs: added constructor that accepts SoapAttributes
+       * XmlSerializationReader.cs: implemented many methods needed to support encoded format.
+       * XmlSerializationReaderInterpreter.cs: added support for encoded format.
+       * XmlSerializationWriter.cs: added support for encoded format.
+       * XmlSerializationWriterInterpreter.cs: added support for encoded format.
+       * XmlTypeMapElementInfo.cs: added some properties needed to support encoded format
+       * XmlTypeMapMemberAttribute.cs: added MappedType property (enum values can be attributes, 
+         and a map is needed for them).
+       * XmlTypeMapMemberElement.cs: small fixes.
+       * XmlTypeMapping.cs: added some properties and methods needed to support encoded format
+       * ReflectionHelper.cs: added. Has some methods shared by the reflection importers.
+
 2003-06-01  Miguel de Icaza  <miguel@ximian.com>
 
        * XmlSerializationReader.cs (UnknownAttribute, UnknownNode,
diff --git a/mcs/class/System.XML/System.Xml.Serialization/ReflectionHelper.cs b/mcs/class/System.XML/System.Xml.Serialization/ReflectionHelper.cs
new file mode 100644 (file)
index 0000000..15ed284
--- /dev/null
@@ -0,0 +1,53 @@
+// 
+// System.Xml.Serialization.ReflectionHelper 
+//
+// Author:
+//   Lluis Sanchez Gual (lluis@ximian.com)
+//
+// Copyright (C) 2003 Ximian, Inc.\r
+//
+
+using System.Reflection;
+using System.Collections;
+\r
+namespace System.Xml.Serialization\r
+{\r
+       internal class ReflectionHelper\r
+       {\r
+               Hashtable _clrTypes = new Hashtable ();
+               Hashtable _schemaTypes = new Hashtable ();
+\r
+               public void RegisterSchemaType (XmlTypeMapping map, string xmlType, string ns)
+               {
+                       string mapKey = xmlType + "/" + ns;
+                       if (!_schemaTypes.ContainsKey (xmlType))
+                               _schemaTypes.Add (mapKey, map);
+               }
+
+               public XmlTypeMapping GetRegisteredSchemaType (string xmlType, string ns)
+               {
+                       string mapKey = xmlType + "/" + ns;
+                       return _schemaTypes[mapKey] as XmlTypeMapping;
+               }
+
+               public void RegisterClrType (XmlTypeMapping map, Type type, string ns)
+               {
+                       if (type == typeof(object)) ns = "";
+                       string mapKey = type.FullName + "/" + ns;
+                       if (!_clrTypes.ContainsKey (mapKey))
+                               _clrTypes.Add (mapKey, map);
+               }
+
+               public XmlTypeMapping GetRegisteredClrType (Type type, string ns)
+               {
+                       if (type == typeof(object)) ns = "";
+                       string mapKey = type.FullName + "/" + ns;
+                       return _clrTypes[mapKey] as XmlTypeMapping;
+               }       \r
+\r
+               public Exception CreateError (XmlTypeMapping map, string message)
+               {
+                       return new InvalidOperationException ("There was an error reflecting '" + map.TypeFullName + "': " + message);
+               }
+       }\r
+}\r
index 11c2b5926c2a003dcd371964c01d8e7b396336f8..df266c5d48a2390df1dfc2aa15717ea36f0111e0 100644 (file)
 \r
 using System.Reflection;\r
 using System.Xml;\r
+using System.Xml.Schema;\r
+using System.Collections;
 \r
 namespace System.Xml.Serialization {\r
        public class SoapReflectionImporter {\r
 \r
+               SoapAttributeOverrides attributeOverrides;\r
+               string initialDefaultNamespace;\r
+               ArrayList includedTypes;
+               ArrayList relatedMaps = new ArrayList ();
+               ReflectionHelper helper = new ReflectionHelper();
+               internal const string EncodingNamespace = "http://schemas.xmlsoap.org/soap/encoding/";
+\r
                #region Constructors\r
 \r
-               [MonoTODO]\r
-               public SoapReflectionImporter ()\r
+               public SoapReflectionImporter (): this (null, null)\r
                { \r
-                       throw new NotImplementedException ();\r
                }\r
 \r
-               [MonoTODO]\r
-               public SoapReflectionImporter (SoapAttributeOverrides attributeOverrides)\r
+               public SoapReflectionImporter (SoapAttributeOverrides attributeOverrides): this (attributeOverrides, null)\r
                { \r
-                       throw new NotImplementedException ();\r
                }\r
 \r
-               [MonoTODO]\r
-               public SoapReflectionImporter (string defaultNamespace)\r
-               { \r
-                       throw new NotImplementedException ();\r
+               public SoapReflectionImporter (string defaultNamespace): this (null, defaultNamespace)\r
+               {\r
                }\r
 \r
-               [MonoTODO]\r
                public SoapReflectionImporter (SoapAttributeOverrides attributeOverrides, string defaultNamespace)\r
                { \r
-                       throw new NotImplementedException ();\r
+                       if (defaultNamespace == null) initialDefaultNamespace = String.Empty;
+                       else initialDefaultNamespace = defaultNamespace;
+
+                       if (attributeOverrides == null) this.attributeOverrides = new SoapAttributeOverrides();
+                       else this.attributeOverrides = attributeOverrides;\r
                }\r
 \r
                #endregion // Constructors\r
 \r
                #region Methods\r
 \r
-               [MonoTODO]\r
                public XmlMembersMapping ImportMembersMapping (string elementName, string ns, XmlReflectionMember[] members)\r
-               { \r
-                       throw new NotImplementedException ();\r
+               {\r
+                       return ImportMembersMapping (elementName, ns, members, true, true, false);\r
                }\r
 \r
-               [MonoTODO]\r
                public XmlMembersMapping ImportMembersMapping (string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors)\r
                { \r
-                       throw new NotImplementedException ();\r
+                       return ImportMembersMapping (elementName, ns, members, hasWrapperElement, writeAccessors, false);\r
                }\r
 \r
-               [MonoTODO]\r
                public XmlMembersMapping ImportMembersMapping (string elementName, string ns, XmlReflectionMember[] members, bool hasWrapperElement, bool writeAccessors, bool validate)\r
                { \r
-                       throw new NotImplementedException ();\r
+                       XmlMemberMapping[] mapping = new XmlMemberMapping[members.Length];
+                       for (int n=0; n<members.Length; n++)
+                       {
+                               XmlTypeMapMember mapMem = CreateMapMember (members[n], ns);
+                               mapping[n] = new XmlMemberMapping (members[n], mapMem);
+                       }
+                       XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, mapping);
+                       mps.RelatedMaps = relatedMaps;\r
+                       mps.Format = SerializationFormat.Encoded;\r
+                       return mps;\r
                }\r
 \r
-               [MonoTODO]\r
                public XmlTypeMapping ImportTypeMapping (Type type)\r
                { \r
-                       throw new NotImplementedException ();\r
+                       return ImportTypeMapping (type, null);\r
                }\r
 \r
-               [MonoTODO]\r
                public XmlTypeMapping ImportTypeMapping (Type type, string defaultNamespace)\r
                { \r
-                       throw new NotImplementedException ();\r
+                       if (type == null)
+                               throw new ArgumentNullException ("type");
+
+                       if (type == typeof (void))
+                               throw new InvalidOperationException ("Type " + type.Name + " may not be serialized.");
+
+                       if (defaultNamespace == null) defaultNamespace = initialDefaultNamespace;
+                       if (defaultNamespace == null) defaultNamespace = string.Empty;
+
+                       XmlTypeMapping map;
+                       switch (TypeTranslator.GetTypeData(type).SchemaType)
+                       {
+                               case SchemaTypes.Class: map = ImportClassMapping (type, defaultNamespace); break;
+                               case SchemaTypes.Array: map = ImportListMapping (type, defaultNamespace); break;
+                               case SchemaTypes.XmlNode: throw CreateTypeException (type);
+                               case SchemaTypes.Primitive: map = ImportPrimitiveMapping (type, defaultNamespace); break;
+                               case SchemaTypes.Enum: map = ImportEnumMapping (type, defaultNamespace); break;
+                               case SchemaTypes.DataSet:
+                               default: throw new NotSupportedException ("Type " + type.FullName + " not supported for XML stialization");
+                       }\r
+                       map.RelatedMaps = relatedMaps;\r
+                       map.Format = SerializationFormat.Encoded;\r
+                       return map;\r
                }\r
 \r
-               [MonoTODO]\r
-               public void IncludeType (Type type)\r
-               { \r
-                       throw new NotImplementedException ();\r
+               XmlTypeMapping CreateTypeMapping (TypeData typeData, string defaultXmlType, string defaultNamespace)
+               {
+                       string membersNamespace = defaultNamespace;
+                       string elementName;
+                       SoapAttributes atts = null;
+                       if (defaultXmlType == null) defaultXmlType = typeData.XmlType;
+
+                       if (!typeData.IsListType)
+                       {
+                               if (attributeOverrides != null) 
+                                       atts = attributeOverrides[typeData.Type];
+                       }
+
+                       if (atts == null) 
+                               atts = new SoapAttributes (typeData.Type);
+
+                       if (atts.SoapType != null)
+                       {
+                               if (atts.SoapType.Namespace != null && atts.SoapType.Namespace != string.Empty)
+                                       membersNamespace = atts.SoapType.Namespace;
+
+                               if (atts.SoapType.TypeName != null && atts.SoapType.TypeName != string.Empty)
+                                       defaultXmlType = atts.SoapType.TypeName;
+                       }
+
+                       elementName = defaultXmlType;
+
+                       if (membersNamespace == null) membersNamespace = "";
+                       XmlTypeMapping map = new XmlTypeMapping (elementName, membersNamespace, typeData, defaultXmlType);
+
+                       relatedMaps.Add (map);
+                       return map;
+               }
+\r
+               XmlTypeMapping ImportClassMapping (Type type, string defaultNamespace)
+               {
+                       if (type.IsValueType) throw CreateStructException (type);
+                       if (type == typeof (object)) defaultNamespace = XmlSchema.Namespace;
+
+                       TypeData typeData = TypeTranslator.GetTypeData (type);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+                       if (map != null) return map;
+
+                       map = CreateTypeMapping (typeData, null, defaultNamespace);
+                       helper.RegisterClrType (map, type, defaultNamespace);
+                       map.MultiReferenceType = true;
+
+                       ClassMap classMap = new ClassMap ();
+                       map.ObjectMap = classMap;
+
+                       // Import members
+
+                       try
+                       {
+                               ICollection members = GetReflectionMembers (type);
+                               foreach (XmlReflectionMember rmember in members)
+                               {
+                                       if (rmember.SoapAttributes.SoapIgnore) continue;
+                                       classMap.AddMember (CreateMapMember (rmember, map.Namespace));
+                               }
+                       }
+                       catch (Exception ex) \r
+                       {
+                               throw helper.CreateError (map, ex.Message);
+                       }
+
+                       // Import derived classes
+
+                       SoapIncludeAttribute[] includes = (SoapIncludeAttribute[])type.GetCustomAttributes (typeof (SoapIncludeAttribute), false);
+                       for (int n=0; n<includes.Length; n++)
+                       {
+                               Type includedType = includes[n].Type;
+                               if (!includedType.IsSubclassOf(type)) throw helper.CreateError (map, "Type '" + includedType.FullName + "' is not a subclass of '" + type.FullName + "'");
+                               map.DerivedTypes.Add (ImportTypeMapping (includedType, defaultNamespace));
+                       }
+
+                       if (type == typeof (object) && includedTypes != null)
+                       {
+                               foreach (Type intype in includedTypes)
+                                       map.DerivedTypes.Add (ImportTypeMapping (intype));
+                       }
+
+                       // Register this map as a derived class of object
+
+                       if (typeData.Type != typeof(object))
+                               ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
+                       
+                       return map;
+               }
+\r
+               XmlTypeMapping ImportListMapping (Type type, string defaultNamespace)
+               {
+                       TypeData typeData = TypeTranslator.GetTypeData (type);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, EncodingNamespace);
+                       if (map != null) return map;
+
+                       ListMap obmap = new ListMap ();
+
+                       map = CreateTypeMapping (typeData, "Array", EncodingNamespace);
+                       helper.RegisterClrType (map, type, EncodingNamespace);
+                       map.MultiReferenceType = true;
+                       map.ObjectMap = obmap;
+
+                       Type itemType = typeData.ListItemType;
+                       TypeData itemTypeData = TypeTranslator.GetTypeData (itemType);
+                       XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (null, itemTypeData);
+                       
+                       if (elem.TypeData.IsComplexType) {
+                               elem.MappedType = ImportTypeMapping (itemType);
+                               elem.DataType = elem.MappedType.XmlType;
+                       }
+                       else
+                               elem.DataType = itemTypeData.XmlType;
+                               
+                       elem.ElementName = "Item";
+                       elem.Namespace = string.Empty;
+                       elem.IsNullable = true; // By default, items are nullable
+
+                       XmlTypeMapElementInfoList list = new XmlTypeMapElementInfoList();
+                       list.Add (elem);
+
+                       obmap.ItemInfo = list;
+                       ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
+
+                       return map;
                }\r
+               \r
+               XmlTypeMapping ImportPrimitiveMapping (Type type, string defaultNamespace)
+               {
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+                       if (map != null) return map;
+                       map = CreateTypeMapping (TypeTranslator.GetTypeData (type), null, defaultNamespace);
+                       helper.RegisterClrType (map, type, defaultNamespace);
+                       return map;
+               }
+\r
+
+               XmlTypeMapping ImportEnumMapping (Type type, string defaultNamespace)
+               {
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
+                       if (map != null) return map;
+                       map = CreateTypeMapping (TypeTranslator.GetTypeData (type), null, defaultNamespace);
+                       helper.RegisterClrType (map, type, defaultNamespace);
+
+                       string [] names = Enum.GetNames (type);
+                       EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember[names.Length];
+                       for (int n=0; n<names.Length; n++)
+                       {
+                               MemberInfo[] mem = type.GetMember (names[n]);
+                               string xmlName = names[n];
+                               object[] atts = mem[0].GetCustomAttributes (typeof(SoapEnumAttribute), false);
+                               if (atts.Length > 0) xmlName = ((SoapEnumAttribute)atts[0]).Name;
+                               members[n] = new EnumMap.EnumMapMember (xmlName, names[n]);
+                       }
+
+                       map.ObjectMap = new EnumMap (members);
+                       ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
+                       return map;
+               }
+
+               public ICollection GetReflectionMembers (Type type)
+               {
+                       ArrayList members = new ArrayList();
+                       PropertyInfo[] properties = type.GetProperties (BindingFlags.Instance | BindingFlags.Public);
+                       foreach (PropertyInfo prop in properties)
+                       {
+                               if (!prop.CanRead) continue;
+                               SoapAttributes atts = attributeOverrides[type, prop.Name];
+                               if (atts == null) atts = new SoapAttributes (prop);
+                               if (atts.SoapIgnore) continue;
+                               XmlReflectionMember member = new XmlReflectionMember(prop.Name, prop.PropertyType, atts);
+                               members.Add (member);
+                       }
+
+                       FieldInfo[] fields = type.GetFields (BindingFlags.Instance | BindingFlags.Public);
+                       foreach (FieldInfo field in fields)
+                       {
+                               SoapAttributes atts = attributeOverrides[type, field.Name];
+                               if (atts == null) atts = new SoapAttributes (field);
+                               if (atts.SoapIgnore) continue;
+                               XmlReflectionMember member = new XmlReflectionMember(field.Name, field.FieldType, atts);
+                               members.Add (member);
+                       }
+                       return members;
+               }
+               
+               private XmlTypeMapMember CreateMapMember (XmlReflectionMember rmember, string defaultNamespace)
+               {
+                       XmlTypeMapMember mapMember;
+                       SoapAttributes atts = rmember.SoapAttributes;
+                       TypeData typeData = TypeTranslator.GetTypeData (rmember.MemberType);
+
+                       if (atts.SoapAttribute != null)
+                       {
+                               // An attribute
+
+                               if (atts.SoapElement != null)
+                                       throw new Exception ("SoapAttributeAttribute and SoapElementAttribute cannot be applied to the same member");
+
+                               XmlTypeMapMemberAttribute mapAttribute = new XmlTypeMapMemberAttribute ();
+                               if (atts.SoapAttribute.AttributeName == null) 
+                                       mapAttribute.AttributeName = rmember.MemberName;
+                               else 
+                                       mapAttribute.AttributeName = atts.SoapAttribute.AttributeName;
+
+                               mapAttribute.DataType = atts.SoapAttribute.DataType;
+                               mapAttribute.Namespace = (atts.SoapAttribute.Namespace != null) ? atts.SoapAttribute.Namespace : "";
+                               if (typeData.IsComplexType)
+                                       mapAttribute.MappedType = ImportTypeMapping (typeData.Type);
+
+                               mapMember = mapAttribute;
+                       }
+                       else
+                       {
+                               if (typeData.SchemaType == SchemaTypes.Array) mapMember = new XmlTypeMapMemberList ();
+                               else mapMember = new XmlTypeMapMemberElement ();
+
+                               // Creates an ElementInfo that identifies the element
+                               XmlTypeMapElementInfoList infoList = new XmlTypeMapElementInfoList();
+                               XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (mapMember, typeData);
+
+                               elem.ElementName = (atts.SoapElement != null && atts.SoapElement.ElementName != null) ? atts.SoapElement.ElementName : rmember.MemberName;
+                               elem.Namespace = string.Empty;
+                               elem.IsNullable = (atts.SoapElement != null) ? atts.SoapElement.IsNullable : false;
+                               elem.DataType = (atts.SoapElement != null && atts.SoapElement.DataType != null) ? atts.SoapElement.DataType : typeData.XmlType;
+                               if (typeData.IsComplexType)
+                                       elem.MappedType = ImportTypeMapping (typeData.Type);
+                               
+                               infoList.Add (elem);
+                               ((XmlTypeMapMemberElement)mapMember).ElementInfo = infoList;
+                       }
+
+                       mapMember.TypeData = typeData;
+                       mapMember.Name = rmember.MemberName;
+                       return mapMember;
+               }\r
+               \r
+               public void IncludeType (Type type)
+               {
+                       if (type == null)
+                               throw new ArgumentNullException ("type");
+
+                       if (includedTypes == null) includedTypes = new ArrayList ();
+                       includedTypes.Add (type);
+               }
 \r
                [MonoTODO]\r
                public void IncludeTypes (ICustomAttributeProvider provider)\r
@@ -85,6 +357,19 @@ namespace System.Xml.Serialization {
                        throw new NotImplementedException ();\r
                }\r
 \r
+               Exception CreateTypeException (Type type)\r
+               {\r
+                       return new NotSupportedException ("The type " + type.FullName + " may not be serialized with SOAP-encoded messages. Set the Use for your message to Literal");\r
+               }\r
+\r
+               Exception CreateStructException (Type type)\r
+               {\r
+                       return new NotSupportedException ("Cannot serialize " + type.FullName + ". Nested structs are not supported with encoded SOAP");\r
+               }\r
+\r
+\r
+               \r
+\r
                #endregion // Methods\r
        }\r
 }\r
index d6a2ead8336aa9f88b24858c32b2d23418d9ab41..84186a0c764bb02d7171fe1da7f9bee6156a9780 100644 (file)
@@ -69,6 +69,11 @@ namespace System.Xml.Serialization
                        return typeData;
                }
 
+               public static bool IsPrimitive (Type type)
+               {
+                       return GetTypeData (type).SchemaType == SchemaTypes.Primitive;
+               }
+
                public static TypeData GetPrimitiveTypeData (string typeName)
                {
                        return (TypeData) primitiveTypes[typeName];
index 75fafc304dcf55020b4ef372e1af1ec1083e8084..7bd259ff1dc1739ebfea41553af900ab9a751f04 100644 (file)
@@ -9,12 +9,15 @@
 //
 
 using System;
+using System.Collections;
 
 namespace System.Xml.Serialization
 {
        public abstract class XmlMapping
        {
                ObjectMap map;
+               ArrayList relatedMaps;
+               SerializationFormat format;
 
                internal XmlMapping ()
                {
@@ -25,9 +28,23 @@ namespace System.Xml.Serialization
                        get { return map; }
                        set { map = value; }
                }
+
+               internal ArrayList RelatedMaps
+               {
+                       get { return relatedMaps; }
+                       set { relatedMaps = value; }
+               }
+
+               internal SerializationFormat Format
+               {
+                       get { return format; }
+                       set { format = value; }
+               }
        }
 
        internal class ObjectMap
        {
        }
+
+       internal enum SerializationFormat { Encoded, Literal }
 }
index b1ab9f13f7b1433bfc1584f3cb6b266a5c626406..9cfbe3af5e97c4fb80fe93663733b6655d74a870 100644 (file)
@@ -21,6 +21,7 @@ namespace System.Xml.Serialization {
                ArrayList includedTypes;
                Hashtable clrTypes = new Hashtable ();
                Hashtable schemaTypes = new Hashtable ();
+               ReflectionHelper helper = new ReflectionHelper();
                int arrayChoiceCount = 1;
 
                #region Constructors
@@ -68,7 +69,9 @@ namespace System.Xml.Serialization {
                                XmlTypeMapMember mapMem = CreateMapMember (members[n], ns);
                                mapping[n] = new XmlMemberMapping (members[n], mapMem);
                        }
-                       return new XmlMembersMapping (elementName, ns, hasWrapperElement, mapping);
+                       XmlMembersMapping mps = new XmlMembersMapping (elementName, ns, hasWrapperElement, mapping);
+                       mps.Format = SerializationFormat.Literal;\r
+                       return mps;\r
                }
 
                public XmlTypeMapping ImportTypeMapping (Type type)
@@ -97,16 +100,21 @@ namespace System.Xml.Serialization {
                        if (defaultNamespace == null) defaultNamespace = initialDefaultNamespace;
                        if (defaultNamespace == null) defaultNamespace = string.Empty;
 
+                       XmlTypeMapping map;
+
                        switch (TypeTranslator.GetTypeData(type).SchemaType)
                        {
-                               case SchemaTypes.Class: return ImportClassMapping (type, root, defaultNamespace);
-                               case SchemaTypes.Array: return ImportListMapping (type, root, defaultNamespace, null, 0);
-                               case SchemaTypes.XmlNode: return ImportXmlNodeMapping (type, root, defaultNamespace);
-                               case SchemaTypes.Primitive: return ImportPrimitiveMapping (type, root, defaultNamespace);
-                               case SchemaTypes.Enum: return ImportEnumMapping (type, root, defaultNamespace);
+                               case SchemaTypes.Class: map = ImportClassMapping (type, root, defaultNamespace); break;
+                               case SchemaTypes.Array: map = ImportListMapping (type, root, defaultNamespace, null, 0); break;
+                               case SchemaTypes.XmlNode: map = ImportXmlNodeMapping (type, root, defaultNamespace); break;
+                               case SchemaTypes.Primitive: map = ImportPrimitiveMapping (type, root, defaultNamespace); break;
+                               case SchemaTypes.Enum: map = ImportEnumMapping (type, root, defaultNamespace); break;
                                case SchemaTypes.DataSet:
                                default: throw new NotSupportedException ("Type " + type.FullName + " not supported for XML stialization");
                        }
+
+                       map.Format = SerializationFormat.Literal;\r
+                       return map;\r
                }
 
                XmlTypeMapping CreateTypeMapping (TypeData typeData, XmlRootAttribute root, string defaultXmlType, string defaultNamespace)
@@ -155,13 +163,13 @@ namespace System.Xml.Serialization {
                XmlTypeMapping ImportClassMapping (Type type, XmlRootAttribute root, string defaultNamespace)
                {
                        TypeData typeData = TypeTranslator.GetTypeData (type);
-                       XmlTypeMapping map = GetRegisteredClrType (type, defaultNamespace);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
                        if (map != null) return map;
 
                        map = CreateTypeMapping (typeData, root, null, defaultNamespace);
                        
-                       RegisterClrType (map, type, defaultNamespace);
-                       RegisterSchemaType (map, map.XmlType, defaultNamespace);
+                       helper.RegisterClrType (map, type, defaultNamespace);
+                       helper.RegisterSchemaType (map, map.XmlType, defaultNamespace);
 
                        ClassMap classMap = new ClassMap ();
                        map.ObjectMap = classMap;
@@ -178,7 +186,7 @@ namespace System.Xml.Serialization {
                                }
                        }
                        catch (Exception ex) {
-                               throw CreateError (map, ex.Message);
+                               throw helper.CreateError (map, ex.Message);
                        }
 
                        // Import derived classes
@@ -187,7 +195,7 @@ namespace System.Xml.Serialization {
                        for (int n=0; n<includes.Length; n++)
                        {
                                Type includedType = includes[n].Type;
-                               if (!includedType.IsSubclassOf(type)) throw CreateError (map, "Type '" + includedType.FullName + "' is not a subclass of '" + type.FullName + "'");
+                               if (!includedType.IsSubclassOf(type)) throw helper.CreateError (map, "Type '" + includedType.FullName + "' is not a subclass of '" + type.FullName + "'");
                                map.DerivedTypes.Add (ImportTypeMapping (includedType, root, defaultNamespace));
                        }
 
@@ -279,7 +287,7 @@ namespace System.Xml.Serialization {
                        string name = baseName;
 
                        do {
-                               XmlTypeMapping foundMap = GetRegisteredSchemaType (name, defaultNamespace);
+                               XmlTypeMapping foundMap = helper.GetRegisteredSchemaType (name, defaultNamespace);
                                if (foundMap == null) nameCount = -1;
                                else if (obmap.Equals (foundMap.ObjectMap)) return foundMap;
                                else name = baseName + (nameCount++);
@@ -291,7 +299,7 @@ namespace System.Xml.Serialization {
 
                        // Register this map as a derived class of object
 
-                       RegisterSchemaType (map, name, defaultNamespace);
+                       helper.RegisterSchemaType (map, name, defaultNamespace);
                        ImportTypeMapping (typeof(object)).DerivedTypes.Add (map);
 
                        return map;
@@ -304,39 +312,39 @@ namespace System.Xml.Serialization {
 
                XmlTypeMapping ImportXmlNodeMapping (Type type, XmlRootAttribute root, string defaultNamespace)
                {
-                       XmlTypeMapping map = GetRegisteredClrType (type, defaultNamespace);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
                        if (map != null) return map;
 
                        // Registers the maps for XmlNode and XmlElement
 
                        XmlTypeMapping nodeMap = CreateTypeMapping (TypeTranslator.GetTypeData (typeof(XmlNode)), root, null, defaultNamespace);
-                       RegisterClrType (nodeMap, typeof(XmlNode), defaultNamespace);
+                       helper.RegisterClrType (nodeMap, typeof(XmlNode), defaultNamespace);
 
                        XmlTypeMapping elemMap = CreateTypeMapping (TypeTranslator.GetTypeData (typeof(XmlElement)), root, null, defaultNamespace);
-                       RegisterClrType (elemMap, typeof(XmlElement), defaultNamespace);
+                       helper.RegisterClrType (elemMap, typeof(XmlElement), defaultNamespace);
 
                        ImportTypeMapping (typeof(object)).DerivedTypes.Add (nodeMap);
                        ImportTypeMapping (typeof(object)).DerivedTypes.Add (elemMap);
                        nodeMap.DerivedTypes.Add (elemMap);
 
-                       return GetRegisteredClrType (type, defaultNamespace);
+                       return helper.GetRegisteredClrType (type, defaultNamespace);
                }
 
                XmlTypeMapping ImportPrimitiveMapping (Type type, XmlRootAttribute root, string defaultNamespace)
                {
-                       XmlTypeMapping map = GetRegisteredClrType (type, defaultNamespace);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
                        if (map != null) return map;
                        map = CreateTypeMapping (TypeTranslator.GetTypeData (type), root, null, defaultNamespace);
-                       RegisterClrType (map, type, defaultNamespace);
+                       helper.RegisterClrType (map, type, defaultNamespace);
                        return map;
                }
 
                XmlTypeMapping ImportEnumMapping (Type type, XmlRootAttribute root, string defaultNamespace)
                {
-                       XmlTypeMapping map = GetRegisteredClrType (type, defaultNamespace);
+                       XmlTypeMapping map = helper.GetRegisteredClrType (type, defaultNamespace);
                        if (map != null) return map;
                        map = CreateTypeMapping (TypeTranslator.GetTypeData (type), root, null, defaultNamespace);
-                       RegisterClrType (map, type, defaultNamespace);
+                       helper.RegisterClrType (map, type, defaultNamespace);
 
                        string [] names = Enum.GetNames (type);
                        EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember[names.Length];
@@ -424,7 +432,10 @@ namespace System.Xml.Serialization {
 
                                mapAttribute.DataType = atts.XmlAttribute.DataType;
                                mapAttribute.Form = atts.XmlAttribute.Form;
-                               mapAttribute.Namespace = (atts.XmlAttribute != null) ? atts.XmlAttribute.Namespace : "";
+                               mapAttribute.Namespace = (atts.XmlAttribute.Namespace != null) ? atts.XmlAttribute.Namespace : "";
+                               if (typeData.IsComplexType)
+                                       mapAttribute.MappedType = ImportTypeMapping (typeData.Type, null, mapAttribute.Namespace);
+
                                mapMember = mapAttribute;
                        }
                        else if (typeData.SchemaType == SchemaTypes.Array)
@@ -445,16 +456,13 @@ namespace System.Xml.Serialization {
                                        // A list
 
                                        XmlTypeMapMemberList member = new XmlTypeMapMemberList ();
-                                       member.ElementName = (atts.XmlArray != null && atts.XmlArray.ElementName != null) ? atts.XmlArray.ElementName : rmember.MemberName;
-                                       member.Namespace = (atts.XmlArray != null && atts.XmlArray.Namespace != null) ? atts.XmlArray.Namespace : defaultNamespace;
-                                       member.ListTypeMapping = ImportListMapping (rmember.MemberType, null, member.Namespace, atts, 0);
 
                                        // Creates an ElementInfo that identifies the array instance. 
                                        member.ElementInfo = new XmlTypeMapElementInfoList();
                                        XmlTypeMapElementInfo elem = new XmlTypeMapElementInfo (member, typeData);
-                                       elem.ElementName = member.ElementName;
-                                       elem.Namespace = member.Namespace;
-                                       elem.MappedType = member.ListTypeMapping;
+                                       elem.ElementName = (atts.XmlArray != null && atts.XmlArray.ElementName != null) ? atts.XmlArray.ElementName : rmember.MemberName;
+                                       elem.Namespace = (atts.XmlArray != null && atts.XmlArray.Namespace != null) ? atts.XmlArray.Namespace : defaultNamespace;
+                                       elem.MappedType = ImportListMapping (rmember.MemberType, null, elem.Namespace, atts, 0);
                                        member.ElementInfo.Add (elem);
                                        mapMember = member;
                                }
@@ -537,39 +545,6 @@ namespace System.Xml.Serialization {
                        includedTypes.Add (type);
                }
 
-               void RegisterSchemaType (XmlTypeMapping map, string xmlType, string ns)
-               {
-                       string mapKey = xmlType + "/" + ns;
-                       if (!schemaTypes.ContainsKey (xmlType))
-                               schemaTypes.Add (mapKey, map);
-               }
-
-               XmlTypeMapping GetRegisteredSchemaType (string xmlType, string ns)
-               {
-                       string mapKey = xmlType + "/" + ns;
-                       return schemaTypes[mapKey] as XmlTypeMapping;
-               }
-
-               void RegisterClrType (XmlTypeMapping map, Type type, string ns)
-               {
-                       if (type == typeof(object)) ns = "";
-                       string mapKey = type.FullName + "/" + ns;
-                       if (!clrTypes.ContainsKey (mapKey))
-                               clrTypes.Add (mapKey, map);
-               }
-
-               XmlTypeMapping GetRegisteredClrType (Type type, string ns)
-               {
-                       if (type == typeof(object)) ns = "";
-                       string mapKey = type.FullName + "/" + ns;
-                       return clrTypes[mapKey] as XmlTypeMapping;
-               }
-
-               Exception CreateError (XmlTypeMapping map, string message)
-               {
-                       return new InvalidOperationException ("There was an error reflecting '" + map.TypeFullName + "': " + message);
-               }
-
                #endregion // Methods
        }
 }
index 61b0296b8033522be6da9c35f1fb6d143565b0e7..9539508f6455617ab1823759aa755fad66664764 100644 (file)
@@ -27,13 +27,20 @@ namespace System.Xml.Serialization {
                {\r
                }\r
 \r
-               public XmlReflectionMember (string name, Type type, XmlAttributes attributes)\r
+               internal XmlReflectionMember (string name, Type type, XmlAttributes attributes)\r
                {\r
                        memberName = name;\r
                        memberType = type;\r
                        xmlAttributes = attributes;\r
                }\r
 \r
+               internal XmlReflectionMember (string name, Type type, SoapAttributes attributes)\r
+               {\r
+                       memberName = name;\r
+                       memberType = type;\r
+                       soapAttributes = attributes;\r
+               }\r
+\r
                #endregion // Constructors\r
 \r
                #region Properties\r
index d24ad45064d65eb8729cc9f793bf85aed0bed4ba..3ad13e00047bcc653e97e8827ffaa78e6f0fd61a 100644 (file)
@@ -13,6 +13,7 @@
 using System;
 using System.Collections;
 using System.Xml;
+using System.Xml.Schema;
 
 namespace System.Xml.Serialization {
        public abstract class XmlSerializationReader {
@@ -22,11 +23,12 @@ namespace System.Xml.Serialization {
                XmlDocument document;
                XmlReader reader;
                ArrayList fixups;
-               ArrayList collFixups;
-               Hashtable readCallbacks;
+               Hashtable collFixups;
+               ArrayList collItemFixups;
                Hashtable typesCallbacks;
                ArrayList noIDTargets;
                Hashtable targets;
+               Hashtable delayedListFixups;
                XmlSerializer eventSource;
 
                string w3SchemaNS;
@@ -44,6 +46,7 @@ namespace System.Xml.Serialization {
                string typeX;
                string arrayType;
                string anyType;
+               XmlQualifiedName arrayQName;
                #endregion
 
                internal void Initialize (XmlReader reader, XmlSerializer eventSource)
@@ -65,6 +68,7 @@ namespace System.Xml.Serialization {
                        anyType = reader.NameTable.Add ("anyType");
                        this.reader = reader;
                        this.eventSource = eventSource;
+                       arrayQName = new XmlQualifiedName ("Array", soapNS);
                        InitIDs ();
                }
                        
@@ -109,24 +113,34 @@ namespace System.Xml.Serialization {
 
                protected void AddFixup (CollectionFixup fixup)
                {
-                       collFixups = EnsureArrayList (collFixups);
-                       collFixups.Add(fixup);
+                       collFixups = EnsureHashtable (collFixups);
+                       collFixups [fixup.Id] = fixup;
+
+                       if (delayedListFixups != null && delayedListFixups.ContainsKey (fixup.Id))
+                               fixup.CollectionItems = delayedListFixups [fixup.Id];
                }
 
                protected void AddFixup (Fixup fixup)
                {
                        fixups = EnsureArrayList (fixups);
-                       fixups.Add(fixup);
+                       fixups.Add (fixup);
+               }
+
+               void AddFixup (CollectionItemFixup fixup)
+               {
+                       collItemFixups = EnsureArrayList (collItemFixups);
+                       collItemFixups.Add(fixup);
                }
 
                protected void AddReadCallback (string name, string ns, Type type, XmlSerializationReadCallback read)
                {
-                       XmlNameTable nt = reader.NameTable;
-                       XmlQualifiedName xqn = new XmlQualifiedName (nt.Add (name), nt.Add (ns));
-                       readCallbacks = EnsureHashtable (readCallbacks);
-                       readCallbacks.Add (xqn, read);
+                       WriteCallbackInfo info = new WriteCallbackInfo ();
+                       info.Type = type;
+                       info.TypeName = name;
+                       info.TypeNs = ns;
+                       info.Callback = read;
                        typesCallbacks = EnsureHashtable (typesCallbacks);
-                       typesCallbacks.Add (xqn, type);
+                       typesCallbacks.Add (new XmlQualifiedName (name, ns), info);
                }
 
                protected void AddTarget (string id, object o)
@@ -247,10 +261,16 @@ namespace System.Xml.Serialization {
                        return (na != string.Empty);
                }
 
-               [MonoTODO ("Implement")]
                protected object GetTarget (string id)
                {
-                       throw new NotImplementedException ();
+                       if (targets == null) return null;
+                       return targets [id];
+               }
+
+               bool TargetReady (string id)
+               {
+                       if (targets == null) return false;
+                       return targets.ContainsKey (id);
                }
 
                [MonoTODO ("Implement")]
@@ -370,32 +390,143 @@ namespace System.Xml.Serialization {
 
                protected object ReadReferencedElement ()
                {
-                       return ReadReferencedElement (null, null);
+                       return ReadReferencedElement (Reader.LocalName, Reader.NamespaceURI);
+               }
+
+               WriteCallbackInfo GetCallbackInfo (XmlQualifiedName qname)
+               {
+                       if (typesCallbacks == null) 
+                       {
+                               typesCallbacks = new Hashtable ();
+                               InitCallbacks ();
+                       }
+                       return (WriteCallbackInfo) typesCallbacks[qname];
                }
 
                protected object ReadReferencedElement (string name, string ns)
                {
-                       string unused;
-                       return ReadReferencingElement (name, ns, false, out unused);
+                       XmlQualifiedName qname = GetXsiType ();
+                       if (qname == null) qname = new XmlQualifiedName (name, ns);
+
+                       string id = Reader.GetAttribute ("id");
+                       object ob;
+
+                       if (qname == arrayQName)
+                       {
+                               CollectionFixup fixup = (collFixups != null) ? (CollectionFixup) collFixups[id] : null;
+                               if (ReadList (out ob))
+                               {
+                                       // List complete (does not contain references)
+                                       if (fixup != null)
+                                       {
+                                               fixup.Callback (fixup.Collection, ob);
+                                               collFixups.Remove (id);
+                                               ob = fixup.Collection;
+                                       }
+                               }
+                               else if (fixup != null) 
+                               {
+                                       fixup.CollectionItems = (object[])ob;
+                                       ob = fixup.Collection;
+                               }
+                       }
+                       else
+                       {
+                               WriteCallbackInfo info = GetCallbackInfo (qname);
+                               if (info == null) throw CreateUnknownTypeException (qname);
+                               ob = info.Callback ();
+                       }
+                       AddTarget (id, ob);
+                       return ob;
                }
 
-               protected void ReadReferencedElements ()
+               bool ReadList (out object resultList)
                {
-                       string unused;
+                       string arrayType = Reader.GetAttribute ("arrayType", soapNS);
+                       XmlQualifiedName qn = ToXmlQualifiedName (arrayType);
+                       int i = qn.Name.LastIndexOf ('[');
+                       string dim = qn.Name.Substring (i);
+                       string itemType = qn.Name.Substring (0,i);
+                       int count = Int32.Parse (dim.Substring (1, dim.Length - 2));
+
+                       Array list;
 
+                       i = itemType.IndexOf ('['); if (i == -1) i = itemType.Length;
+                       string baseType = itemType.Substring (0,i);
+                       string arrayTypeName;
+
+                       if (qn.Namespace == XmlSchema.Namespace)
+                               arrayTypeName = TypeTranslator.GetPrimitiveTypeData (baseType).Type.FullName + itemType.Substring (i);
+                       else
+                       {
+                               WriteCallbackInfo info = GetCallbackInfo (new XmlQualifiedName (baseType,qn.Namespace));
+                               arrayTypeName = info.Type.FullName + itemType.Substring (i) + ", " + info.Type.Assembly.FullName;
+                       }
+
+                       list = Array.CreateInstance (Type.GetType (arrayTypeName), count);
+
+                       bool listComplete = true;
+
+                       Reader.ReadStartElement ();
+                       for (int n=0; n<count; n++)
+                       {
+                               Reader.MoveToContent ();
+                               string refid = Reader.GetAttribute ("href");
+                               string id;
+                               object item = ReadReferencingElement (itemType, qn.Namespace, out id);
+                               if (id == null) 
+                                       list.SetValue (item,n);
+                               else
+                               {
+                                       AddFixup (new CollectionItemFixup (list, n, id));
+                                       listComplete = false;
+                               }
+                       }
+                       Reader.ReadEndElement ();
+
+                       resultList = list;
+                       return listComplete;
+               }
+               
+               protected void ReadReferencedElements ()
+               {
                        reader.MoveToContent();
                        XmlNodeType nt = reader.NodeType;
                        while (nt != XmlNodeType.EndElement && nt != XmlNodeType.None) {
-                               ReadReferencingElement (null, null, true, out unused);
+                               ReadReferencedElement ();
                                reader.MoveToContent ();
                                nt = reader.NodeType;
                        }
+
+                       // Fix arrays
+
+                       if (collItemFixups != null)
+                       {
+                               foreach (CollectionItemFixup itemFixup in collItemFixups)
+                                       itemFixup.Collection.SetValue (GetTarget (itemFixup.Id), itemFixup.Index);
+                       }
+
+                       // Fills collections
+
+                       if (collFixups != null)
+                       {
+                               ICollection cfixups = collFixups.Values;
+                               foreach (CollectionFixup fixup in cfixups)
+                                       fixup.Callback (fixup.Collection, fixup.CollectionItems);
+                       }
+
+                       // Fills class instances
+
+                       if (fixups != null)
+                       {
+                               foreach (Fixup fixup in fixups)
+                                       fixup.Callback (fixup);
+                       }
                }
 
-               [MonoTODO ("Implement")]
                protected object ReadReferencingElement (out string fixupReference)
                {
-                       return ReadReferencingElement (null, null, false, out fixupReference);
+                       return ReadReferencingElement (Reader.LocalName, Reader.NamespaceURI, false, out fixupReference);
                }
 
                protected object ReadReferencingElement (string name, string ns, out string fixupReference)
@@ -403,13 +534,60 @@ namespace System.Xml.Serialization {
                        return ReadReferencingElement (name, ns, false, out fixupReference);
                }
 
-               [MonoTODO]
                protected object ReadReferencingElement (string name,
                                                         string ns,
                                                         bool elementCanBeType,
                                                         out string fixupReference)
                {
-                       throw new NotImplementedException ();
+                       if (ReadNull ())
+                       {
+                               fixupReference = null;
+                               return null;
+                       }
+
+                       string refid = Reader.GetAttribute ("href");
+
+                       if (refid == string.Empty || refid == null)
+                       {
+                               fixupReference = null;
+
+                               XmlQualifiedName qname = GetXsiType ();
+                               if (qname == null) qname = new XmlQualifiedName (name, ns);
+
+                               if (qname == arrayQName)
+                               {
+                                       delayedListFixups = EnsureHashtable (delayedListFixups);
+                                       fixupReference = "__<" + delayedListFixups.Count + ">";
+                                       object items;
+                                       ReadList (out items);
+                                       delayedListFixups [fixupReference] = items;
+                                       return null;
+                               }
+                               else
+                               {
+                                       WriteCallbackInfo info = GetCallbackInfo (qname);
+                                       if (info == null)
+                                               return ReadTypedPrimitive (qname);
+                                       else
+                                               return info.Callback();
+                               }
+                       }
+                       else
+                       {
+                               if (refid.StartsWith ("#")) refid = refid.Substring (1);
+
+                               Reader.ReadStartElement ();
+                               if (TargetReady (refid))
+                               {
+                                       fixupReference = null;
+                                       return GetTarget (refid);
+                               }
+                               else
+                               {
+                                       fixupReference = refid;
+                                       return null;
+                               }
+                       }
                }
 
                protected IXmlSerializable ReadSerializable (IXmlSerializable serializable)
@@ -426,9 +604,9 @@ namespace System.Xml.Serialization {
                        return (value + reader.ReadString ());
                }
 
-               protected object ReadTypedPrimitive (XmlQualifiedName type)
+               protected object ReadTypedPrimitive (XmlQualifiedName qname)
                {
-                       XmlQualifiedName qname = GetXsiType ();
+                       if (qname == null) qname = GetXsiType ();
                        TypeData typeData = TypeTranslator.GetPrimitiveTypeData (qname.Name);
                        if (typeData == null || typeData.SchemaType != SchemaTypes.Primitive) throw new InvalidOperationException ("Unknown type: " + qname.Name);
                        return XmlCustomFormatter.FromXmlString (typeData.Type, Reader.ReadElementString ());
@@ -446,7 +624,6 @@ namespace System.Xml.Serialization {
                [MonoTODO ("Implement")]
                protected void Referenced (object o)
                {
-                       throw new NotImplementedException ();
                }
 
                protected Array ShrinkArray (Array a, int length, Type elementType, bool isNullable)
@@ -592,7 +769,19 @@ namespace System.Xml.Serialization {
                        }
                        
                        eventSource.OnUnknownNode (new XmlNodeEventArgs(line_number, line_position, Reader.LocalName, Reader.Name, Reader.NamespaceURI, Reader.NodeType, o, Reader.Value));
-                       if (Reader.NodeType != XmlNodeType.Attribute)
+                       if (Reader.NodeType == XmlNodeType.Attribute)
+                       {
+                               XmlAttribute att = (XmlAttribute) ReadXmlNode (false);
+                               UnknownAttribute (o, att);
+                               return;
+                       }
+                       else if (Reader.NodeType == XmlNodeType.Element)
+                       {
+                               XmlElement elem = (XmlElement) ReadXmlNode (false);
+                               UnknownElement (o, elem);
+                               return;
+                       }
+                       else
                        {
                                Reader.Skip();
                                if (Reader.ReadState == ReadState.EndOfFile) 
@@ -607,30 +796,28 @@ namespace System.Xml.Serialization {
 
                #endregion // Methods
 
+               class WriteCallbackInfo
+               {
+                       public Type Type;
+                       public string TypeName;
+                       public string TypeNs;
+                       public XmlSerializationReadCallback Callback;
+               }
+
                protected class CollectionFixup {
                        
-                       #region Fields
-
                        XmlSerializationCollectionFixupCallback callback;
                        object collection;
                        object collectionItems;
+                       string id;
 
-                       #endregion // Fields
-
-                       #region Constructors
-
-                       [MonoTODO]
-                       public CollectionFixup (object collection, XmlSerializationCollectionFixupCallback callback, object collectionItems)
+                       public CollectionFixup (object collection, XmlSerializationCollectionFixupCallback callback, string id)
                        {
                                this.callback = callback;
                                this.collection = collection;
-                               this.collectionItems = collectionItems;
+                               this.id = id;
                        }
 
-                       #endregion // Constructors
-
-                       #region Properties
-
                        public XmlSerializationCollectionFixupCallback Callback { 
                                get { return callback; }
                        }
@@ -639,41 +826,37 @@ namespace System.Xml.Serialization {
                                get { return collection; }
                        }
 
-                       public object CollectionItems {
-                               get { return collectionItems; }
+                       public object Id {
+                               get { return id; }
                        }
 
-                       #endregion // Properties
+                       internal object CollectionItems
+                       {
+                               get { return collectionItems; }
+                               set { collectionItems = value; }
+                       }
                }
 
                protected class Fixup {
 
-                       #region Fields
-
                        object source;
                        string[] ids;
                        XmlSerializationFixupCallback callback;
 
-                       #endregion // Fields
-
-                       #region Constructors
-
-                       [MonoTODO]
                        public Fixup (object o, XmlSerializationFixupCallback callback, int count) 
                        {
+                               this.source = o;
                                this.callback = callback;
+                               this.ids = new string[count];
                        }
 
-                       [MonoTODO]
                        public Fixup (object o, XmlSerializationFixupCallback callback, string[] ids)
                        {
+                               this.source = o;
+                               this.ids = ids;
                                this.callback = callback;
                        }
 
-                       #endregion // Constructors
-
-                       #region Properties
-
                        public XmlSerializationFixupCallback Callback {
                                get { return callback; }
                        }
@@ -686,9 +869,37 @@ namespace System.Xml.Serialization {
                                get { return source; }
                                set { source = value; }
                        }
+               }
+
+               protected class CollectionItemFixup \r
+               {
+                       Array list;
+                       int index;
+                       string id;
+
+                       public CollectionItemFixup (Array list, int index, string id)
+                       {
+                               this.list = list;
+                               this.index = index;
+                               this.id = id;
+                       }
+
+                       public Array Collection\r
+                       {
+                               get { return list; }
+                       }
+
+                       public int Index\r
+                       {
+                               get { return index; }
+                       }
 
-                       #endregion // Properties
+                       public string Id\r
+                       {
+                               get { return id; }
+                       }
                }
+
        }
 }
 
index eaaf0ecc19aad6ea550c1a90ee085a963b0911af..277dbb83db4e473eb56f5827468e5eb2358c8e67 100644 (file)
@@ -16,14 +16,28 @@ namespace System.Xml.Serialization
        public class XmlSerializationReaderInterpreter: XmlSerializationReader
        {
                XmlMapping _typeMap;
+               SerializationFormat _format;
 
                public XmlSerializationReaderInterpreter(XmlMapping typeMap)
                {
                        _typeMap = typeMap;
+                       _format = typeMap.Format;
                }
 
                protected override void InitCallbacks ()
                {
+                       ArrayList maps = _typeMap.RelatedMaps;
+                       if (maps != null)
+                       {
+                               foreach (XmlTypeMapping map in maps)  \r
+                               {
+                                       if (map.TypeData.SchemaType == SchemaTypes.Class || map.TypeData.SchemaType == SchemaTypes.Enum)
+                                       {
+                                               ReaderCallbackInfo info = new ReaderCallbackInfo (this, map);
+                                               AddReadCallback (map.XmlType, map.Namespace, map.TypeData.Type, new XmlSerializationReadCallback (info.ReadObject));\r
+                                       }\r
+                               }\r
+                       }\r
                }
 
                protected override void InitIDs ()
@@ -34,11 +48,34 @@ namespace System.Xml.Serialization
                {
                        Reader.MoveToContent();
                        if (_typeMap is XmlTypeMapping)
-                               return ReadObject ((XmlTypeMapping)_typeMap, true, true);
+                       {
+                               if (_format == SerializationFormat.Literal)
+                                       return ReadObject ((XmlTypeMapping)_typeMap, true, true);
+                               else
+                                       return ReadEncodedObject ((XmlTypeMapping)_typeMap);
+                       }
                        else
                                return ReadMessage ((XmlMembersMapping)_typeMap);
                }
 
+               object ReadEncodedObject (XmlTypeMapping typeMap)
+               {
+                       object ob = null;\r
+                       Reader.MoveToContent();\r
+                       if (Reader.NodeType == System.Xml.XmlNodeType.Element) \r
+                       {\r
+                               if (Reader.LocalName == typeMap.ElementName && Reader.NamespaceURI == typeMap.Namespace)\r
+                                       ob = ReadReferencedElement();\r
+                               else \r
+                                       throw CreateUnknownNodeException();\r
+                       }\r
+                       else \r
+                               UnknownNode(null);\r
+\r
+                       ReadReferencedElements();\r
+                       return ob;\r
+               }
+
                object ReadMessage (XmlMembersMapping typeMap)
                {
                        object[] parameters = new object[typeMap.Count];
@@ -64,6 +101,9 @@ namespace System.Xml.Serialization
                        else
                                ReadMembers ((ClassMap)typeMap.ObjectMap, parameters, true);
 
+                       if (_format == SerializationFormat.Encoded)
+                               ReadReferencedElements();\r
+\r
                        return parameters;
                }
 
@@ -84,7 +124,7 @@ namespace System.Xml.Serialization
                {
                        if (isNullable && ReadNull()) return null;
 
-            if (checkType) 
+                       if (checkType) 
                        {
                 System.Xml.XmlQualifiedName t = GetXsiType();
                                if (t != null) 
@@ -131,7 +171,7 @@ namespace System.Xml.Serialization
 
                                        if (member != null) 
                                        {
-                                               SetMemberValue (member, ob, XmlCustomFormatter.FromXmlString (member.TypeData.Type, Reader.Value), isValueList);
+                                               SetMemberValue (member, ob, GetValueFromXmlString (Reader.Value, member.TypeData, member.MappedType), isValueList);
                                        }
                                        else if (IsXmlnsAttribute(Reader.Name)) 
                                        {
@@ -166,6 +206,7 @@ namespace System.Xml.Serialization
 
                        int[] indexes = null;
                        object[] flatLists = null;
+                       Fixup fixup = null;
 
                        if (map.FlatLists != null) 
                        {
@@ -175,6 +216,13 @@ namespace System.Xml.Serialization
                                        if (IsReadOnly (mem, ob, isValueList)) flatLists[mem.FlatArrayIndex] = mem.GetValue (ob);
                        }
 
+                       if (_format == SerializationFormat.Encoded)
+                       {
+                               FixupCallbackInfo info = new FixupCallbackInfo (this, map, isValueList);
+                               fixup = new Fixup(ob, new XmlSerializationFixupCallback(info.FixupMembers), map.ElementMembers.Count);\r
+                               AddFixup (fixup);\r
+                       }
+
                        while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) 
                        {
                                if (Reader.NodeType == System.Xml.XmlNodeType.Element) 
@@ -184,8 +232,31 @@ namespace System.Xml.Serialization
                                        {
                                                if (info.Member.GetType() == typeof (XmlTypeMapMemberList))
                                                {
-                                                       if (IsReadOnly (info.Member, ob, isValueList)) ReadListElement (info.MappedType, info.IsNullable, info.Member.GetValue (ob), false);
-                                                       else  SetMemberValue (info.Member, ob, ReadListElement (info.MappedType, info.IsNullable, null, true), isValueList);
+                                                       if (_format == SerializationFormat.Encoded && info.MultiReferenceType)
+                                                       {
+                                                               object list = ReadReferencingElement (out fixup.Ids[info.Member.Index]);
+                                                               if (fixup.Ids[info.Member.Index] == null)       // Already read\r
+                                                               {
+                                                                       if (IsReadOnly (info.Member, ob, isValueList)) throw CreateReadOnlyCollectionException (info.TypeData.FullTypeName);
+                                                                       else SetMemberValue (info.Member, ob, list, isValueList);
+                                                               }\r
+                                                               else if (!info.MappedType.TypeData.Type.IsArray)\r
+                                                               {\r
+                                                                       if (IsReadOnly (info.Member, ob, isValueList)) 
+                                                                               list = GetMemberValue (info.Member, ob, isValueList);
+                                                                       else { 
+                                                                               list = CreateList (info.MappedType.TypeData.Type);
+                                                                               SetMemberValue (info.Member, ob, list, isValueList);
+                                                                       }
+                                                                       AddFixup (new CollectionFixup (list, new XmlSerializationCollectionFixupCallback (FillList), fixup.Ids[info.Member.Index]));
+                                                                       fixup.Ids[info.Member.Index] = null;    // The member already has the value, no further fix needed.
+                                                               }\r
+                                                       }
+                                                       else
+                                                       {
+                                                               if (IsReadOnly (info.Member, ob, isValueList)) ReadListElement (info.MappedType, info.IsNullable, GetMemberValue (info.Member, ob, isValueList), false);
+                                                               else SetMemberValue (info.Member, ob, ReadListElement (info.MappedType, info.IsNullable, null, true), isValueList);
+                                                       }
                                                        readFlag[info.Member.Index] = true;
                                                }
                                                else if (info.Member.GetType() == typeof (XmlTypeMapMemberFlatList))
@@ -201,8 +272,16 @@ namespace System.Xml.Serialization
                                                }
                                                else if (info.Member.GetType() == typeof(XmlTypeMapMemberElement))
                                                {
-                                                       SetMemberValue (info.Member, ob, ReadObjectElement (info), isValueList);
+                                                       object val;
                                                        readFlag[info.Member.Index] = true;
+                                                       if (_format == SerializationFormat.Encoded && info.MultiReferenceType) \r
+                                                       {
+                                                               val = ReadReferencingElement (out fixup.Ids[info.Member.Index]);
+                                                               if (fixup.Ids[info.Member.Index] == null)       // already read
+                                                                       SetMemberValue (info.Member, ob, val, isValueList);
+                                                       }
+                                                       else 
+                                                               SetMemberValue (info.Member, ob, ReadObjectElement (info), isValueList);
                                                }
                                                else
                                                        throw new InvalidOperationException ("Unknown member type");
@@ -235,6 +314,18 @@ namespace System.Xml.Serialization
                        }               
                }
 
+               internal void FixupMembers (ClassMap map, object obfixup, bool isValueList)
+               {
+                       Fixup fixup = (Fixup)obfixup;
+                       ICollection members = map.ElementMembers;
+                       string[] ids = fixup.Ids;
+                       foreach (XmlTypeMapMember member in members)
+                       {
+                               if (ids[member.Index] != null)
+                                       SetMemberValue (member, fixup.Source, GetTarget(ids[member.Index]), isValueList);
+                       }
+               }
+
                bool IsReadOnly (XmlTypeMapMember member, object ob, bool isValueList)
                {
                        if (isValueList) return false;
@@ -247,25 +338,42 @@ namespace System.Xml.Serialization
                        else member.SetValue (ob, value);
                }
 
+               object GetMemberValue (XmlTypeMapMember member, object ob, bool isValueList)
+               {
+                       if (isValueList) return ((object[])ob)[member.Index];
+                       else return member.GetValue (ob);
+               }
+
                object ReadObjectElement (XmlTypeMapElementInfo elem)
                {
-                       if (elem.IsPrimitive)
+                       switch (elem.TypeData.SchemaType)
                        {
-                               if (elem.TypeData.SchemaType == SchemaTypes.XmlNode)
+                               case SchemaTypes.XmlNode:
                                        return ReadXmlNode (true);
-                               else if (elem.IsNullable) 
-                                       return XmlCustomFormatter.FromXmlString (elem.TypeData.Type, ReadNullableString ());
-                               else 
-                                       return XmlCustomFormatter.FromXmlString (elem.TypeData.Type, Reader.ReadElementString ());
-                       }
-                       else if (elem.MappedType.TypeData.SchemaType == SchemaTypes.Array) {
-                               return ReadListElement (elem.MappedType, elem.IsNullable, null, true);
-                       }
-                       else if (elem.MappedType.TypeData.SchemaType == SchemaTypes.Enum) {
-                               return GetEnumValue (elem.MappedType, Reader.ReadElementString());
+
+                               case SchemaTypes.Primitive:
+                               case SchemaTypes.Enum:
+                                       if (elem.IsNullable) return GetValueFromXmlString (ReadNullableString (), elem.TypeData, elem.MappedType);
+                                       else return GetValueFromXmlString (Reader.ReadElementString (), elem.TypeData, elem.MappedType);
+
+                               case SchemaTypes.Array:
+                                       return ReadListElement (elem.MappedType, elem.IsNullable, null, true);
+
+                               case SchemaTypes.Class:
+                               case SchemaTypes.DataSet:
+                                       return ReadObject (elem.MappedType, elem.IsNullable, true);
+
+                               default:
+                                       throw new NotSupportedException ("Invalid value type");
                        }
-                       else
-                               return ReadObject (elem.MappedType, elem.IsNullable, true);
+               }
+
+               object GetValueFromXmlString (string value, TypeData typeData, XmlTypeMapping typeMap)
+               {
+                       if (typeData.SchemaType == SchemaTypes.Enum)
+                               return GetEnumValue (typeMap, value);
+                       else 
+                               return XmlCustomFormatter.FromXmlString (typeData.Type, value);
                }
 
                object ReadListElement (XmlTypeMapping typeMap, bool isNullable, object list, bool canCreateInstance)
@@ -339,6 +447,32 @@ namespace System.Xml.Serialization
                                return Activator.CreateInstance (listType);
                }
 
+               void FillList (object list, object items)
+               {
+                       CopyEnumerableList (items, list);
+               }
+
+               void CopyEnumerableList (object source, object dest)
+               {
+                       if (dest == null) throw CreateReadOnlyCollectionException (source.GetType().FullName);
+
+                       object[] param = new object[1];
+                       MethodInfo mi = dest.GetType().GetMethod ("Add");
+                       foreach (object ob in (IEnumerable)source)
+                       {
+                               param[0] = ob;
+                               mi.Invoke (dest, param);
+                       }
+               }
+
+               int GetListCount (TypeData listType, object ob)
+               {
+                       if (listType.Type.IsArray)
+                               return ((Array)ob).Length;
+                       else
+                               return (int) listType.Type.GetProperty ("Count").GetValue(ob,null);
+               }
+
                object ReadXmlNodeElement (XmlTypeMapping typeMap, bool isNullable)
                {
                        return ReadXmlNode (false);
@@ -364,5 +498,41 @@ namespace System.Xml.Serialization
                        EnumMap map = (EnumMap) typeMap.ObjectMap;
                        return Enum.Parse (typeMap.TypeData.Type, map.GetEnumName (val));
                }
+
+               class FixupCallbackInfo
+               {
+                       XmlSerializationReaderInterpreter _sri;
+                       ClassMap _map;
+                       bool _isValueList;
+
+                       public FixupCallbackInfo (XmlSerializationReaderInterpreter sri, ClassMap map, bool isValueList)
+                       {
+                               _sri = sri;
+                               _map = map;
+                               _isValueList = isValueList;
+                       }
+
+                       public void FixupMembers (object fixup)
+                       {
+                               _sri.FixupMembers (_map, fixup, _isValueList);
+                       }
+               }
+
+               class ReaderCallbackInfo
+               {
+                       XmlSerializationReaderInterpreter _sri;
+                       XmlTypeMapping _typeMap;
+
+                       public ReaderCallbackInfo (XmlSerializationReaderInterpreter sri, XmlTypeMapping typeMap)
+                       {
+                               _sri = sri;
+                               _typeMap = typeMap;
+                       }
+
+                       internal object ReadObject ()
+                       {
+                               return _sri.ReadObject (_typeMap, true, true);
+                       }
+               }
        }
 }
index 70cbb3c777d58e3248fcccdbf93e57594714c065..7829eb34f5e52440a27d6e3096ca902aa57fd9e4 100644 (file)
@@ -13,18 +13,20 @@ using System.Collections;
 using System.Text;
 using System.Xml;
 using System.Xml.Schema;
+using System.Runtime.Serialization;
 
 namespace System.Xml.Serialization {
        public abstract class XmlSerializationWriter {
 
                #region Fields
 
-               Hashtable references;
-               int referenceCount;
+               ObjectIDGenerator idGenerator;
                int qnameCount;
 
                ArrayList namespaces;
                XmlWriter writer;
+               Queue referencedElements;
+               Hashtable callbacks;
 
                #endregion // Fields
 
@@ -34,8 +36,6 @@ namespace System.Xml.Serialization {
                protected XmlSerializationWriter ()
                {
                        qnameCount = 0;
-                       references = new Hashtable ();
-                       referenceCount = 0;
                }
 
                #endregion // Constructors
@@ -66,10 +66,16 @@ namespace System.Xml.Serialization {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO ("Implement")]
                protected void AddWriteCallback (Type type, string typeName, string typeNs, XmlSerializationWriteCallback callback)
                {
-                       throw new NotImplementedException ();
+                       WriteCallbackInfo info = new WriteCallbackInfo ();
+                       info.Type = type;
+                       info.TypeName = typeName;
+                       info.TypeNs = typeNs;
+                       info.Callback = callback;
+
+                       if (callbacks == null) callbacks = new Hashtable ();
+                       callbacks.Add (type, info);
                }
 
                protected Exception CreateMismatchChoiceException (string value, string elementName, string enumValue)
@@ -158,28 +164,38 @@ namespace System.Xml.Serialization {
 
                private string GetId (object o, bool addToReferencesList)
                {
-                       referenceCount += 1;
-                       string id = String.Format ("id{0}", referenceCount);
-                       if (addToReferencesList)
-                               references[o] = id;
-                       return id;
+                       if (idGenerator == null) idGenerator = new ObjectIDGenerator ();
+
+                       bool firstTime;
+                       long lid = idGenerator.GetId (o, out firstTime);
+                       return String.Format ("id{0}", lid);
                }
 
-               [MonoTODO ("Need to check for namespace conflicts before blindly allocating qN")]
-               private string GetQualifiedName (string name, string ns)
+               
+               bool AlreadyQueued (object ob)
                {
-                       string prefix;
+                       if (idGenerator == null) return false;
 
-                       if (ns == XmlSchema.Namespace)
-                               prefix = "xsd";
-                       else
+                       bool firstTime;
+                       idGenerator.HasId (ob, out firstTime);
+                       return !firstTime;
+               }
+
+               private string GetNamespacePrefix (string ns)
+               {
+                       string prefix = Writer.LookupPrefix (ns);
+                       if (prefix == null) \r
                        {
-                               qnameCount += 1;
-                               prefix = String.Format ("q{0}", qnameCount);
+                               prefix = String.Format ("q{0}", ++qnameCount);
                                WriteAttribute ("xmlns", prefix, null, ns);
                        }
+                       return prefix;
+               }
 
-                       return String.Format ("{0}:{1}", prefix, name);
+               [MonoTODO ("Need to check for namespace conflicts before blindly allocating qN")]
+               private string GetQualifiedName (string name, string ns)
+               {
+                       return String.Format ("{0}:{1}", GetNamespacePrefix (ns), name);
                }
 
                protected abstract void InitCallbacks ();
@@ -220,18 +236,29 @@ namespace System.Xml.Serialization {
                        if (value == null)
                                return;
 
-                       Writer.WriteStartAttribute (prefix, localName, ns);
-                       WriteValue (value);
-                       Writer.WriteEndAttribute ();
+                       Writer.WriteAttributeString (prefix, localName, ns, value);
                }
 
-               [MonoTODO ("Implement")]
                protected void WriteElementEncoded (XmlNode node, string name, string ns, bool isNullable, bool any)
                {
-                       throw new NotImplementedException ();
+                       if (name != string.Empty)
+                       {
+                               if (node == null)
+                               {
+                                       if (isNullable)
+                                               WriteNullTagEncoded (name, ns);
+                               }
+                               else
+                               {
+                                       Writer.WriteStartElement (name, ns);
+                                       node.WriteTo (Writer);
+                                       Writer.WriteEndElement ();
+                               }
+                       }
+                       else
+                               node.WriteTo (Writer);
                }
 
-               [MonoTODO ("Implement")]
                protected void WriteElementLiteral (XmlNode node, string name, string ns, bool isNullable, bool any)
                {
                        if (name != string.Empty)
@@ -410,10 +437,12 @@ namespace System.Xml.Serialization {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO ("Implement")]
                protected void WriteNullableStringEncoded (string name, string ns, string value, XmlQualifiedName xsiType)
                {
-                       throw new NotImplementedException ();
+                       if (value != null)
+                               WriteElementString (name, ns, value, xsiType);
+                       else
+                               WriteNullTagEncoded (name, ns);
                }
 
                [MonoTODO ("Implement")]
@@ -428,17 +457,12 @@ namespace System.Xml.Serialization {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO ("Implement")]
                protected void WriteNullableStringLiteral (string name, string ns, string value)
                {
                        if (value != null)
                                WriteElementString (name, ns, value, null);
                        else
-                       {
-                               WriteStartElement (name, ns);
-                               WriteAttribute ("xsi","nil", ns, "true");
-                               WriteEndElement ();
-                       }
+                               WriteNullTagLiteral (name, ns);
                }
 
                [MonoTODO ("Implement")]
@@ -458,10 +482,11 @@ namespace System.Xml.Serialization {
                        WriteNullTagEncoded (name, String.Empty);
                }
 
-               [MonoTODO ("Implement")]
                protected void WriteNullTagEncoded (string name, string ns)
                {
-                       throw new NotImplementedException ();
+                       WriteStartElement (name, ns);
+                       WriteAttribute ("xsi","null", XmlSchema.InstanceNamespace, "1");
+                       WriteEndElement ();
                }
 
                protected void WriteNullTagLiteral (string name)
@@ -491,16 +516,66 @@ namespace System.Xml.Serialization {
                        WritePotentiallyReferencingElement (n, ns, o, ambientType, suppressReference, false);
                }
 
-               [MonoTODO ("Implement")]
                protected void WritePotentiallyReferencingElement (string n, string ns, object o, Type ambientType, bool suppressReference, bool isNullable)
                {
-                       throw new NotImplementedException ();
+                       if (o == null) 
+                       {
+                               if (isNullable) WriteNullTagEncoded (n, ns);
+                               return;
+                       }
+
+                       WriteStartElement (n, ns, o, true);
+
+                       CheckReferenceQueue ();
+
+                       if (callbacks.ContainsKey (o.GetType ()))
+                       {
+                               WriteCallbackInfo info = (WriteCallbackInfo) callbacks[o.GetType()];
+                               if (o.GetType ().IsEnum) {
+                                       info.Callback (o);
+                               }
+                               else if (suppressReference) {
+                                       Writer.WriteAttributeString ("id", GetId (o, false));
+                                       if (ambientType != o.GetType ()) WriteXsiType(info.TypeName, info.TypeNs);
+                                       info.Callback (o);
+                               }
+                               else {
+                                       if (!AlreadyQueued (o)) referencedElements.Enqueue (o);
+                                       Writer.WriteAttributeString ("href", "#" + GetId (o, true));
+                               }
+                       }
+                       else
+                       {
+                               // Must be a primitive type
+                               TypeData td = TypeTranslator.GetTypeData (o.GetType ());
+                               if (td.SchemaType != SchemaTypes.Primitive)
+                                       throw new InvalidOperationException ("Invalid type: " + o.GetType().FullName);
+                               WriteXsiType(td.XmlType, XmlSchema.Namespace);
+                               Writer.WriteString (XmlCustomFormatter.ToXmlString (o));
+                       }
+
+                       WriteEndElement (o);
                }
 
-               [MonoTODO ("Implement")]
                protected void WriteReferencedElements ()
                {
-                       throw new NotImplementedException ();
+                       if (referencedElements == null) return;
+                       if (callbacks == null) return;
+
+                       while (referencedElements.Count > 0)
+                       {
+                               object o = referencedElements.Dequeue ();
+                               TypeData td = TypeTranslator.GetTypeData (o.GetType ());
+                               WriteCallbackInfo info = (WriteCallbackInfo) callbacks[o.GetType()];
+                               WriteStartElement (info.TypeName, info.TypeNs, o, true);
+                               Writer.WriteAttributeString ("id", GetId (o, false));
+
+                               if (td.SchemaType != SchemaTypes.Array) // Array use its own "arrayType" attribute
+                                       WriteXsiType(info.TypeName, info.TypeNs);
+
+                               info.Callback (o);
+                               WriteEndElement (o);
+                       }
                }
 
                protected void WriteReferencingElement (string n, string ns, object o)
@@ -508,12 +583,34 @@ namespace System.Xml.Serialization {
                        WriteReferencingElement (n, ns, o, false);
                }
 
-               [MonoTODO ("Implement")]
                protected void WriteReferencingElement (string n, string ns, object o, bool isNullable)
                {
-                       throw new NotImplementedException ();
+                       if (o == null) 
+                       {
+                               if (isNullable) WriteNullTagEncoded (n, ns);
+                               return;
+                       }
+                       else
+                       {
+                               CheckReferenceQueue ();
+                               if (!AlreadyQueued (o)) referencedElements.Enqueue (o);
+
+                               Writer.WriteStartElement (n, ns);
+                               Writer.WriteAttributeString ("href", "#" + GetId (o, true));
+                               Writer.WriteEndElement ();
+                       }
                }
 
+               void CheckReferenceQueue ()
+               {
+                       if (referencedElements == null)  \r
+                       {
+                               referencedElements = new Queue ();
+                               InitCallbacks ();
+                       }
+               }
+
+
                [MonoTODO ("Implement")]
                protected void WriteSerializable (IXmlSerializable serializable, string name, string ns, bool isNullable)
                {
@@ -551,13 +648,15 @@ namespace System.Xml.Serialization {
                {
                        WriteState oldState = Writer.WriteState;
 
-                       if (writePrefixed) {
+                       if (writePrefixed && ns != string.Empty) {
                                name = XmlCustomFormatter.FromXmlName (name);
-                               Writer.WriteStartElement (String.Empty, name, ns);
+                               string prefix = Writer.LookupPrefix (ns);
+                               if (prefix == null) prefix = "q" + (++qnameCount);
+                               Writer.WriteStartElement (prefix, name, ns);
                        } else
                                Writer.WriteStartElement (name, ns);
 
-                       if (oldState == WriteState.Prolog) {
+                       if ((o == null) || (oldState == WriteState.Prolog && !TypeTranslator.IsPrimitive (o.GetType()))) {
                                WriteAttribute ("xmlns","xsd",XmlSchema.Namespace,XmlSchema.Namespace);
                                WriteAttribute ("xmlns","xsi",XmlSchema.InstanceNamespace,XmlSchema.InstanceNamespace);
                        }
@@ -613,11 +712,19 @@ namespace System.Xml.Serialization {
                protected void WriteXsiType (string name, string ns)
                {
                        if (ns != null && ns != string.Empty)
-                               WriteAttribute ("xsi", "type", ns, GetQualifiedName (name, ns));
+                               WriteAttribute (GetNamespacePrefix (XmlSchema.InstanceNamespace), "type", ns, GetQualifiedName (name, ns));
                        else
-                               WriteAttribute ("xsi", "type", ns, name);
+                               WriteAttribute (GetNamespacePrefix (XmlSchema.InstanceNamespace), "type", ns, name);
                }
                
                #endregion
+
+               class WriteCallbackInfo
+               {
+                       public Type Type;
+                       public string TypeName;
+                       public string TypeNs;
+                       public XmlSerializationWriteCallback Callback;
+               }
        }
 }
index fc5702fd7052b4638c1f38d38ac6dac920fb72c8..8a7236bc615120db32e584906785f4b185b46eb3 100644 (file)
 using System;
 using System.Collections;
 using System.Reflection;
+using System.Xml.Schema;
 
 namespace System.Xml.Serialization
 {
        internal class XmlSerializationWriterInterpreter: XmlSerializationWriter
        {
                XmlMapping _typeMap;
+               SerializationFormat _format;
 
                public XmlSerializationWriterInterpreter(XmlMapping typeMap)
                {
                        _typeMap = typeMap;
+                       _format = typeMap.Format;
                }
 
                protected override void InitCallbacks ()
                {
+                       ArrayList maps = _typeMap.RelatedMaps;
+                       if (maps != null)
+                       {
+                               foreach (XmlTypeMapping map in maps)  {
+                                       CallbackInfo info = new CallbackInfo (this, map);
+                                       if (map.TypeData.SchemaType == SchemaTypes.Enum) AddWriteCallback(map.TypeData.Type, map.XmlType, map.Namespace, new XmlSerializationWriteCallback (info.WriteObject));\r
+                                       else AddWriteCallback(map.TypeData.Type, map.XmlType, map.Namespace, new XmlSerializationWriteCallback (info.WriteEnum));\r
+                               }\r
+                       }\r
                }
 
                internal override void WriteObject (object ob)
@@ -33,39 +45,65 @@ namespace System.Xml.Serialization
                        if (_typeMap is XmlTypeMapping)
                        {
                                XmlTypeMapping mp = (XmlTypeMapping) _typeMap;
-                               WriteObject (mp, ob, mp.ElementName, mp.Namespace, true, false);
+                               if (_format == SerializationFormat.Literal)
+                                       WriteObject (mp, ob, mp.ElementName, mp.Namespace, true, false, true);
+                               else
+                                       WritePotentiallyReferencingElement (mp.ElementName, mp.Namespace, ob, mp.TypeData.Type, true, false);
                        }
                        else if (ob is object[])
                                WriteMessage ((XmlMembersMapping)_typeMap, (object[]) ob);
                        else
                                throw CreateUnknownTypeException (ob);
+
+                       WriteReferencedElements ();
                }
 
-               void WriteObject (XmlTypeMapping typeMap, object ob, string element, string namesp, bool isNullable, bool needType)
+               internal void WriteObject (XmlTypeMapping typeMap, object ob, string element, string namesp, bool isNullable, bool needType, bool writeWrappingElem)
                {
                        if (ob == null)
                        {
-                               if (isNullable) WriteNullTagLiteral(element, namesp);
+                               if (isNullable) 
+                               {
+                                       if (_format == SerializationFormat.Literal) WriteNullTagLiteral(element, namesp);
+                                       else WriteNullTagEncoded (element, namesp);
+                               }
+                               return;
+                       }
+
+                       if (ob is XmlNode)
+                       {
+                               if (_format == SerializationFormat.Literal) WriteElementLiteral((XmlNode)ob, "", "", true, false);
+                               else WriteElementEncoded((XmlNode)ob, "", "", true, false);
                                return;
                        }
 
                        XmlTypeMapping map = typeMap.GetRealTypeMap (ob.GetType().FullName);
-                       if (map == null)
+
+                       if (map == null) 
                        {
                                WriteTypedPrimitive (element, namesp, ob, true);
+                               return;
                        }
-                       else 
+
+                       if (writeWrappingElem)
                        {
-                               if (map != typeMap) needType = true;
-                               switch (map.TypeData.SchemaType)
-                               {
-                                       case SchemaTypes.Class: WriteObjectElement (map, ob, element, namesp, needType); break;
-                                       case SchemaTypes.Array: WriteListElement (map, ob, element, namesp, needType); break;
-                                       case SchemaTypes.XmlNode: WriteXmlNodeElement (map, ob, element, namesp, needType); break;
-                                       case SchemaTypes.Primitive: WriteTypedPrimitive (element, namesp, ob, needType); break;
-                                       case SchemaTypes.Enum: WriteEnumElement (map, ob, element, namesp, needType); break;
-                               }
+                               if (map != typeMap || _format == SerializationFormat.Encoded) needType = true;
+                               WriteStartElement (element, namesp, ob);
                        }
+
+                       if (needType) 
+                               WriteXsiType(map.XmlType, map.Namespace);
+
+                       switch (map.TypeData.SchemaType)
+                       {
+                               case SchemaTypes.Class: WriteObjectElement (map, ob, element, namesp); break;
+                               case SchemaTypes.Array: WriteListElement (map, ob, element, namesp); break;
+                               case SchemaTypes.Primitive: WritePrimitiveElement (map, ob, element, namesp); break;
+                               case SchemaTypes.Enum: WriteEnumElement (map, ob, element, namesp); break;
+                       }
+
+                       if (writeWrappingElem)
+                               WriteEndElement (ob);
                }
 
                void WriteMessage (XmlMembersMapping membersMap, object[] parameters)
@@ -73,7 +111,13 @@ namespace System.Xml.Serialization
                        if (membersMap.HasWrapperElement) {
                                WriteStartDocument();\r
                                // TopLevelElement();\r
-                               WriteStartElement(membersMap.ElementName, membersMap.Namespace);\r
+                               WriteStartElement(membersMap.ElementName, membersMap.Namespace, (_format == SerializationFormat.Encoded));\r
+\r
+                               if (Writer.LookupPrefix (XmlSchema.Namespace) == null)\r
+                                       WriteAttribute ("xmlns","xsd",XmlSchema.Namespace,XmlSchema.Namespace);
+       
+                               if (Writer.LookupPrefix (XmlSchema.InstanceNamespace) == null)\r
+                                       WriteAttribute ("xmlns","xsi",XmlSchema.InstanceNamespace,XmlSchema.InstanceNamespace);\r
                        }\r
                        \r
                        WriteMembers ((ClassMap)membersMap.ObjectMap, parameters, true);\r
@@ -82,15 +126,10 @@ namespace System.Xml.Serialization
                                WriteEndElement();
                }
 
-               void WriteObjectElement (XmlTypeMapping typeMap, object ob, string element, string namesp, bool needType)
+               void WriteObjectElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
                {
-                       WriteStartElement(element, namesp, ob);
-                       if (needType) 
-                               WriteXsiType(typeMap.XmlType, typeMap.Namespace);
-
                        ClassMap map = (ClassMap)typeMap.ObjectMap;
                        WriteMembers (map, ob, false);
-                       WriteEndElement (ob);
                }
 
                void WriteMembers (ClassMap map, object ob, bool isValueList)
@@ -102,7 +141,7 @@ namespace System.Xml.Serialization
                        {
                                foreach (XmlTypeMapMemberAttribute attr in attributes) {
                                        if (MemberHasValue (attr, ob, isValueList))
-                                               WriteAttribute(attr.AttributeName, attr.Namespace, XmlCustomFormatter.ToXmlString (GetMemberValue (attr, ob, isValueList)));
+                                               WriteAttribute (attr.AttributeName, attr.Namespace, GetStringValue (attr.MappedType, GetMemberValue (attr, ob, isValueList)));
                                }
                        }
 
@@ -113,7 +152,7 @@ namespace System.Xml.Serialization
                                if (extraAtts != null) \r
                                {
                                        foreach (XmlAttribute attr in extraAtts)
-                                               WriteAttribute(attr.LocalName, attr.NamespaceURI, attr.Value);
+                                               WriteAttribute (attr.LocalName, attr.NamespaceURI, attr.Value);
                                }
                        }
 
@@ -131,12 +170,7 @@ namespace System.Xml.Serialization
                                        if (memType == typeof(XmlTypeMapMemberList))
                                        {
                                                if (memberValue != null) \r
-                                               {
-                                                       XmlTypeMapMemberList mm = (XmlTypeMapMemberList)member;
-                                                       WriteStartElement(mm.ElementName, mm.Namespace, memberValue);
-                                                       WriteListContent (member.TypeData, (ListMap) mm.ListTypeMapping.ObjectMap, memberValue);
-                                                       WriteEndElement (memberValue);
-                                               }
+                                                       WriteMemberElement ((XmlTypeMapElementInfo) member.ElementInfo[0], memberValue);
                                        }
                                        else if (memType == typeof(XmlTypeMapMemberFlatList))
                                        {
@@ -182,29 +216,64 @@ namespace System.Xml.Serialization
 
                void WriteMemberElement (XmlTypeMapElementInfo elem, object memberValue)
                {
-                       if (elem.IsPrimitive)
+                       switch (elem.TypeData.SchemaType)
                        {
-                               if (elem.TypeData.SchemaType == SchemaTypes.XmlNode)
-                                       WriteElementLiteral(((XmlNode)memberValue), elem.ElementName, elem.Namespace, elem.IsNullable, false);
-                               else if (elem.IsNullable)
-                                       WriteNullableStringLiteral (elem.ElementName, elem.Namespace, XmlCustomFormatter.ToXmlString (memberValue));
-                               else 
-                                       WriteElementString (elem.ElementName, elem.Namespace, XmlCustomFormatter.ToXmlString (memberValue));
+                               case SchemaTypes.XmlNode:
+                                       if (_format == SerializationFormat.Literal) WriteElementLiteral(((XmlNode)memberValue), elem.ElementName, elem.Namespace, elem.IsNullable, false);
+                                       else WriteElementEncoded(((XmlNode)memberValue), elem.ElementName, elem.Namespace, elem.IsNullable, false);
+                                       break;
+
+                               case SchemaTypes.Enum:
+                               case SchemaTypes.Primitive:
+                                       if (_format == SerializationFormat.Literal) {
+                                               if (elem.IsNullable) WriteNullableStringLiteral (elem.ElementName, elem.Namespace, GetStringValue (elem.MappedType, memberValue));\r
+                                               else WriteElementString (elem.ElementName, elem.Namespace, GetStringValue (elem.MappedType, memberValue));\r
+                                       }
+                                       else {
+                                               if (elem.IsNullable) WriteNullableStringEncoded (elem.ElementName, elem.Namespace, GetStringValue (elem.MappedType, memberValue), new XmlQualifiedName (elem.DataType, elem.DataTypeNamespace));\r
+                                               else WriteElementString (elem.ElementName, elem.Namespace, GetStringValue (elem.MappedType, memberValue), new XmlQualifiedName (elem.DataType, elem.DataTypeNamespace));\r
+                                       }
+                                       break;
+
+                               case SchemaTypes.Array:
+                                       if (elem.MappedType.MultiReferenceType) 
+                                               WriteReferencingElement (elem.ElementName, elem.Namespace, memberValue, elem.IsNullable);
+                                       else {
+                                               WriteStartElement(elem.ElementName, elem.Namespace, memberValue);
+                                               WriteListContent (elem.TypeData, (ListMap) elem.MappedType.ObjectMap, memberValue);
+                                               WriteEndElement (memberValue);
+                                       }
+                                       break;
+
+                               case SchemaTypes.Class:
+                                       if (elem.MappedType.MultiReferenceType) {
+                                               if (elem.MappedType.TypeData.Type == typeof(object))
+                                                       WritePotentiallyReferencingElement (elem.ElementName, elem.Namespace, memberValue, null, false, elem.IsNullable);
+                                               else
+                                                       WriteReferencingElement (elem.ElementName, elem.Namespace, memberValue, elem.IsNullable);
+                                       }
+                                       else WriteObject (elem.MappedType, memberValue, elem.ElementName, elem.Namespace, elem.IsNullable, false, true);
+                                       break;
+
+                               case SchemaTypes.DataSet:
+                                       throw new NotSupportedException ("Invalid type");
+
+                               default:
+                                       throw new NotSupportedException ("Invalid value type");
                        }
-                       else if (elem.TypeData.SchemaType == SchemaTypes.Enum)
-                               WriteElementString(elem.ElementName, elem.Namespace, GetEnumXmlValue (elem.MappedType, memberValue));\r
-                       else
-                               WriteObject (elem.MappedType, memberValue, elem.ElementName, elem.Namespace, elem.IsNullable, false);
                }
 
-               void WriteListElement (XmlTypeMapping typeMap, object ob, string element, string namesp, bool needType)
+               void WriteListElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
                {
-                       WriteStartElement(element, namesp, ob);
-                       if (needType) 
-                               WriteXsiType(typeMap.XmlType, typeMap.Namespace);
-
+                       if (_format == SerializationFormat.Encoded)
+                       {
+                               string n, ns;
+                               int itemCount = GetListCount (typeMap.TypeData, ob);
+                               ((ListMap) typeMap.ObjectMap).GetArrayType (itemCount, out n, out ns);
+                               string arrayType = (ns != string.Empty) ? FromXmlQualifiedName (new XmlQualifiedName(n,ns)) : n;
+                               WriteAttribute ("arrayType", SoapReflectionImporter.EncodingNamespace, arrayType);
+                       }
                        WriteListContent (typeMap.TypeData, (ListMap) typeMap.ObjectMap, ob);
-                       WriteEndElement (ob);
                }
 
                void WriteListContent (TypeData listType, ListMap map, object ob)
@@ -248,6 +317,14 @@ namespace System.Xml.Serialization
                                throw new Exception ("Unsupported collection type");
                }
 
+               int GetListCount (TypeData listType, object ob)
+               {
+                       if (listType.Type.IsArray)
+                               return ((Array)ob).Length;
+                       else
+                               return (int) listType.Type.GetProperty ("Count").GetValue(ob,null);
+               }
+
                void WriteAnyElementContent (XmlTypeMapMemberAnyElement member, object memberValue)
                {
                        if (member.TypeData.Type == typeof (XmlElement)) {
@@ -260,7 +337,10 @@ namespace System.Xml.Serialization
                                if (elem is XmlElement) 
                                {
                                        if (member.IsElementDefined (elem.Name, elem.NamespaceURI))
-                                               WriteElementLiteral(elem, "", "", false, true);
+                                       {
+                                               if (_format == SerializationFormat.Literal) WriteElementLiteral (elem, "", "", false, true);
+                                               else WriteElementEncoded (elem, "", "", false, true);
+                                       }
                                        else
                                                throw CreateUnknownAnyElementException (elem.Name, elem.NamespaceURI);
                                }
@@ -269,17 +349,22 @@ namespace System.Xml.Serialization
                        }
                }
 
-               void WriteXmlNodeElement (XmlTypeMapping typeMap, object ob, string element, string namesp, bool needType)
+               void WritePrimitiveElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
                {
-                       WriteElementLiteral((XmlNode)ob, "", "", true, false);
+                       Writer.WriteString (GetStringValue (typeMap, ob));
                }
 
-               void WriteEnumElement (XmlTypeMapping typeMap, object ob, string element, string namesp, bool needType)
+               void WriteEnumElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
                {
-                       Writer.WriteStartElement(element, namesp);\r
-                       if (needType) WriteXsiType(typeMap.XmlType, typeMap.Namespace);\r
                        Writer.WriteString (GetEnumXmlValue (typeMap, ob));\r
-                       Writer.WriteEndElement();
+               }
+
+               string GetStringValue (XmlTypeMapping typeMap, object value)
+               {
+                       if (typeMap != null && typeMap.TypeData.SchemaType == SchemaTypes.Enum)
+                               return GetEnumXmlValue (typeMap, value);
+                       else
+                               return XmlCustomFormatter.ToXmlString (value);
                }
 
                string GetEnumXmlValue (XmlTypeMapping typeMap, object ob)
@@ -287,5 +372,28 @@ namespace System.Xml.Serialization
                        EnumMap map = (EnumMap)typeMap.ObjectMap;
                        return map.GetXmlName (ob.ToString ());
                }
+
+               class CallbackInfo
+               {
+                       XmlSerializationWriterInterpreter _swi;
+                       XmlTypeMapping _typeMap;
+
+                       public CallbackInfo (XmlSerializationWriterInterpreter swi, XmlTypeMapping typeMap)
+                       {
+                               _swi = swi;
+                               _typeMap = typeMap;
+                       }
+
+                       internal void WriteObject (object ob)
+                       {
+                               _swi.WriteObject (_typeMap, ob, _typeMap.ElementName, _typeMap.Namespace, false, true, false);
+                       }
+
+                       internal void WriteEnum (object ob)
+                       {
+                               _swi.WriteObject (_typeMap, ob, _typeMap.ElementName, _typeMap.Namespace, false, false, false);
+                       }
+               }
+
        }
 }
index c2bdd313ee6aac6b7adcd487557d82cdbc6eb032..4adc486ddfa7ef67492cad08ef6c08c6964aa782 100644 (file)
@@ -64,6 +64,15 @@ namespace System.Xml.Serialization
                        set { _dataType = value; }
                }
 
+               public string DataTypeNamespace
+               {
+                       get 
+                       { 
+                               if (_mappedType == null) return XmlSchema.Namespace;
+                               else return _mappedType.Namespace;
+                       }
+               }
+
                public XmlSchemaForm Form 
                {
                        get { return _form; }
@@ -99,6 +108,15 @@ namespace System.Xml.Serialization
                        set { _nestingLevel = value; }
                }
 
+               internal bool MultiReferenceType\r
+               {\r
+                       get \r
+                       { \r
+                               if (_mappedType != null) return _mappedType.MultiReferenceType;\r
+                               else return false;\r
+                       }\r
+               }\r
+\r
                public override bool Equals (object other)
                {
                        XmlTypeMapElementInfo oinfo = (XmlTypeMapElementInfo)other;
index 6eebf15298e3cfd8d19b3846622f7b1becefaaa5..fd80b628be7bbf3e0c3bed5cbcbd3a5101533def 100644 (file)
@@ -21,6 +21,7 @@ namespace System.Xml.Serialization
                string _dataType;
                string _namespace = "";
                XmlSchemaForm _form;
+               XmlTypeMapping _mappedType;
 
                public XmlTypeMapMemberAttribute()
                {
@@ -49,5 +50,11 @@ namespace System.Xml.Serialization
                        get { return _form; }
                        set { _form = value; }
                }
+
+               public XmlTypeMapping MappedType
+               {
+                       get { return _mappedType; }
+                       set { _mappedType = value; }
+               }
        }
 }
index 3e36a18f517091971b4aa2e6d6bab6832f2bba1b..f112725e9b7897e0b38c69a2877bb9e07a31aa65 100644 (file)
@@ -48,6 +48,8 @@ namespace System.Xml.Serialization
                        }
                        else
                        {
+                               if (memberValue == null)
+                                       return (XmlTypeMapElementInfo) _elementInfo[0];
                                Type type = memberValue.GetType();
                                foreach (XmlTypeMapElementInfo elem in _elementInfo)
                                        if (elem.TypeData.Type == type) return elem;
@@ -61,26 +63,19 @@ namespace System.Xml.Serialization
 
        internal class XmlTypeMapMemberList : XmlTypeMapMemberElement
        {
-               XmlTypeMapping _listMap;
-               string _elementName;
-               string _namespace;
-
                public XmlTypeMapping ListTypeMapping
                {
-                       get { return _listMap; }
-                       set { _listMap = value; }
+                       get { return ((XmlTypeMapElementInfo) ElementInfo[0]).MappedType; }
                }
 
                public string ElementName
                {
-                       get { return _elementName; }
-                       set { _elementName = value; }
+                       get { return ((XmlTypeMapElementInfo) ElementInfo[0]).ElementName; }
                }
 
                public string Namespace
                {
-                       get { return _namespace; }
-                       set { _namespace = value; }
+                       get { return ((XmlTypeMapElementInfo) ElementInfo[0]).Namespace; }
                }
        }
 
index 7c8f677d49b90be8aebf1e9c3171069adb2a70ac..513d857a2a0360a561cd7a46eb0945d61e9f5de9 100644 (file)
@@ -20,6 +20,7 @@ namespace System.Xml.Serialization
                private string ns;\r
                private string xmlType;\r
                TypeData type;\r
+               bool multiReferenceType = false;\r
 \r
                ArrayList _derivedTypes = new ArrayList();\r
 \r
@@ -67,6 +68,12 @@ namespace System.Xml.Serialization
                        set { _derivedTypes = value; }\r
                }\r
 \r
+               internal bool MultiReferenceType\r
+               {\r
+                       get { return multiReferenceType; }\r
+                       set { multiReferenceType = value; }\r
+               }\r
+\r
                internal XmlTypeMapping GetRealTypeMap (string objectFullTypeName)\r
                {\r
                        // Returns the map for a subtype of this map's type\r
@@ -219,6 +226,34 @@ namespace System.Xml.Serialization
                        return null;\r
                }\r
 \r
+               public void GetArrayType (int itemCount, out string localName, out string ns)\r
+               {\r
+                       string arrayDim;\r
+                       if (itemCount != -1) arrayDim = "[" + itemCount + "]";\r
+                       else arrayDim = "[]";\r
+\r
+                       XmlTypeMapElementInfo info = (XmlTypeMapElementInfo) _itemInfo[0];\r
+                       if (info.TypeData.SchemaType == SchemaTypes.Array)\r
+                       {\r
+                               string nm;\r
+                               ((ListMap)info.MappedType.ObjectMap).GetArrayType (-1, out nm, out ns);\r
+                               localName = nm + arrayDim;\r
+                       }\r
+                       else \r
+                       {\r
+                               if (info.MappedType != null)\r
+                               {\r
+                                       localName = info.MappedType.XmlType + arrayDim;\r
+                                       ns = info.MappedType.Namespace;\r
+                               }\r
+                               else \r
+                               {\r
+                                       localName = info.DataType + arrayDim;\r
+                                       ns = info.DataTypeNamespace;\r
+                               }\r
+                       }\r
+               }\r
+\r
                public override bool Equals (object other)\r
                {\r
                        ListMap lmap = other as ListMap;\r