2007-04-20 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlSerializationReaderInterpreter.cs
index fb46de152f1354a1f18c0f6062f4af9b022e0d9f..f2b8e212d1d1d3afa608fd91cf20d86e2b31d61f 100644 (file)
@@ -39,6 +39,7 @@ namespace System.Xml.Serialization
                XmlMapping _typeMap;
                SerializationFormat _format;
                static readonly XmlQualifiedName AnyType = new XmlQualifiedName("anyType", System.Xml.Schema.XmlSchema.Namespace);
+               static readonly object [] empty_array = new object [0];
 
                public XmlSerializationReaderInterpreter(XmlMapping typeMap)
                {
@@ -115,6 +116,16 @@ namespace System.Xml.Serialization
 
                        if (typeMap.HasWrapperElement)
                        {
+                               // bug #79988: out parameters need to be initialized if they 
+                               // are value types
+                               ArrayList members = ((ClassMap) typeMap.ObjectMap).AllMembers;
+                               for (int n = 0; n < members.Count; n++) {
+                                       XmlTypeMapMember mem = (XmlTypeMapMember) members [n];
+                                       if (!mem.IsReturnValue && mem.TypeData.IsValueType)
+                                               SetMemberValueFromAttr (mem, parameters, CreateInstance (
+                                                       mem.TypeData.Type), true);
+                               }
+
                                if (_format == SerializationFormat.Encoded)
                                {
                                        while (Reader.NodeType == System.Xml.XmlNodeType.Element)
@@ -125,13 +136,20 @@ namespace System.Xml.Serialization
                                                Reader.MoveToContent ();
                                        }
                                }
-                               
-                               while (Reader.NodeType != System.Xml.XmlNodeType.EndElement) 
+
+                               while (Reader.NodeType != System.Xml.XmlNodeType.EndElement &&
+                                      // it could be an empty root element
+                                      Reader.ReadState == ReadState.Interactive)
                                {
                                        if (Reader.IsStartElement(typeMap.ElementName, typeMap.Namespace) 
                                            || _format == SerializationFormat.Encoded)  
                                        {
-                                               if (Reader.IsEmptyElement) { Reader.Skip(); Reader.MoveToContent(); continue; }
+                                               ReadAttributeMembers ((ClassMap)typeMap.ObjectMap, parameters, true);
+                                               if (Reader.IsEmptyElement) {
+                                                       Reader.Skip();
+                                                       Reader.MoveToContent();
+                                                       continue;
+                                               }
                                                Reader.ReadStartElement();
                                                ReadMembers ((ClassMap)typeMap.ObjectMap, parameters, true, false);
                                                ReadEndElement();
@@ -205,7 +223,7 @@ namespace System.Xml.Serialization
                                        return ReadTypedPrimitive (AnyType);
             }
 
-                       object ob = Activator.CreateInstance (typeMap.TypeData.Type);
+                       object ob = Activator.CreateInstance (typeMap.TypeData.Type, true);
 
                        Reader.MoveToElement();
                        bool isEmpty = Reader.IsEmptyElement;
@@ -222,20 +240,8 @@ namespace System.Xml.Serialization
                        ReadMembers ((ClassMap) typeMap.ObjectMap, ob, false, false);
                }
 
-               void ReadMembers (ClassMap map, object ob, bool isValueList, bool readByOrder)
+               void ReadAttributeMembers (ClassMap map, object ob, bool isValueList)
                {
-                       // Set the default values of the members
-                       if (map.MembersWithDefault != null)
-                       {
-                               ArrayList members = map.MembersWithDefault;
-                               for (int n=0; n<members.Count; n++) {
-                                       XmlTypeMapMember mem = (XmlTypeMapMember) members[n];
-                                       SetMemberValueFromAttr (mem, ob, mem.DefaultValue, isValueList);
-                               }
-                       }
-                       
-                       // Reads attributes
-
                        XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
                        int anyAttributeIndex = 0;
                        object anyAttributeArray = null;
@@ -280,7 +286,24 @@ namespace System.Xml.Serialization
                                anyAttributeArray = ShrinkArray ((Array)anyAttributeArray, anyAttributeIndex, anyAttrMember.TypeData.Type.GetElementType(), true);
                                SetMemberValue (anyAttrMember, ob, anyAttributeArray, isValueList);
                        }
+                       Reader.MoveToElement ();
+               }
+
+               void ReadMembers (ClassMap map, object ob, bool isValueList, bool readByOrder)
+               {
+                       // Set the default values of the members
+                       if (map.MembersWithDefault != null)
+                       {
+                               ArrayList members = map.MembersWithDefault;
+                               for (int n=0; n<members.Count; n++) {
+                                       XmlTypeMapMember mem = (XmlTypeMapMember) members[n];
+                                       SetMemberValueFromAttr (mem, ob, mem.DefaultValue, isValueList);
+                               }
+                       }
                        
+                       // Reads attributes
+                       ReadAttributeMembers (map, ob, isValueList);
+
                        if (!isValueList)
                        {
                                Reader.MoveToElement();
@@ -600,7 +623,7 @@ namespace System.Xml.Serialization
                                        return ReadObject (elem.MappedType, elem.IsNullable, true);
 
                                case SchemaTypes.XmlSerializable:
-                                       object ob = Activator.CreateInstance (elem.TypeData.Type);
+                                       object ob = Activator.CreateInstance (elem.TypeData.Type, true);
                                        return ReadSerializable ((IXmlSerializable)ob);
 
                                default:
@@ -711,7 +734,7 @@ namespace System.Xml.Serialization
                        else    // Must be IEnumerable
                        {
                                if (list == null) {
-                                       if (canCreateInstance) list = Activator.CreateInstance (type);
+                                       if (canCreateInstance) list = Activator.CreateInstance (type, true);
                                        else throw CreateReadOnlyCollectionException (type.FullName);
                                }
 
@@ -720,12 +743,17 @@ namespace System.Xml.Serialization
                        }
                }
 
+               object CreateInstance (Type type)
+               {
+                       return Activator.CreateInstance (type, empty_array);
+               }
+
                object CreateList (Type listType)
                {
                        if (listType.IsArray)
                                return EnsureArrayIndex (null, 0, listType.GetElementType());
                        else
-                               return Activator.CreateInstance (listType);
+                               return Activator.CreateInstance (listType, true);
                }
                
                object InitializeList (TypeData listType)
@@ -733,7 +761,7 @@ namespace System.Xml.Serialization
                        if (listType.Type.IsArray)
                                return null;
                        else
-                               return Activator.CreateInstance (listType.Type);
+                               return Activator.CreateInstance (listType.Type, true);
                }
 
                void FillList (object list, object items)
@@ -797,7 +825,7 @@ namespace System.Xml.Serialization
                        {
                                if (Reader.LocalName == typeMap.ElementName && Reader.NamespaceURI == typeMap.Namespace)
                                {
-                                       object ob = Activator.CreateInstance (typeMap.TypeData.Type);
+                                       object ob = Activator.CreateInstance (typeMap.TypeData.Type, true);
                                        return ReadSerializable ((IXmlSerializable)ob);
                                }
                                else