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)
{
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)
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();
}
else
{
- if (Reader.LocalName != rootMap.ElementName || Reader.NamespaceURI != rootMap.Namespace)
+ if (!rootMap.IsAny && (Reader.LocalName != rootMap.ElementName || Reader.NamespaceURI != rootMap.Namespace))
throw CreateUnknownNodeException();
return ReadObject (rootMap, rootMap.IsNullable, true);
return ReadTypedPrimitive (AnyType);
}
- object ob = Activator.CreateInstance (typeMap.TypeData.Type);
+ object ob = CreateInstance (typeMap.TypeData.Type, true);
Reader.MoveToElement();
bool isEmpty = Reader.IsEmptyElement;
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;
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 readBySoapOrder)
+ {
+ // Reads attributes
+ ReadAttributeMembers (map, ob, isValueList);
+
if (!isValueList)
{
Reader.MoveToElement();
object[] flatLists = null;
object[] flatListsChoices = null;
Fixup fixup = null;
- int ind = 0;
+ int ind = -1;
int maxInd;
- if (readByOrder) {
+ if (readBySoapOrder) {
if (map.ElementMembers != null) maxInd = map.ElementMembers.Count;
- else maxInd = 0;
+ else maxInd = -1;
}
else
maxInd = int.MaxValue;
AddFixup (fixup);
}
- while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && (ind < maxInd))
+ XmlTypeMapMember previousMember = null;
+ while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && (ind < maxInd - 1))
{
if (Reader.NodeType == System.Xml.XmlNodeType.Element)
{
XmlTypeMapElementInfo info;
- if (readByOrder) {
- info = map.GetElement (ind++);
+ if (readBySoapOrder) {
+ info = map.GetElement (Reader.LocalName, Reader.NamespaceURI, ind);
}
else if (hasAnyReturnMember) {
info = (XmlTypeMapElementInfo) ((XmlTypeMapMemberElement)map.ReturnMember).ElementInfo[0];
hasAnyReturnMember = false;
}
- else
- info = map.GetElement (Reader.LocalName, Reader.NamespaceURI);
-
+ else {
+ if (map.IsOrderDependentMap) {
+ info = map.GetElement (Reader.LocalName, Reader.NamespaceURI, ind);
+ }
+ else
+ info = map.GetElement (Reader.LocalName, Reader.NamespaceURI);
+ }
+
if (info != null && !readFlag[info.Member.Index] )
{
+ if (info.Member != previousMember)
+ {
+ ind = info.ExplicitOrder + 1;
+ // If the member is a flat list don't increase the index, since the next element may
+ // be another item of the list. This is a fix for Xamarin bug #9193.
+ if (info.Member is XmlTypeMapMemberFlatList)
+ ind--;
+ previousMember = info.Member;
+ }
+
if (info.Member.GetType() == typeof (XmlTypeMapMemberList))
{
if (_format == SerializationFormat.Encoded && info.MultiReferenceType)
}
else
UnknownNode(ob);
-
Reader.MoveToContent();
}
void SetMemberValue (XmlTypeMapMember member, object ob, object value, bool isValueList)
{
- if (isValueList) ((object[])ob)[member.GlobalIndex] = value;
- else {
+ var memberType = member.TypeData.Type;
+ if (value != null && !value.GetType().IsAssignableFrom (memberType))
+ value = XmlSerializationWriterInterpreter.ImplicitConvert (value, memberType);
+
+ if (isValueList)
+ ((object[])ob)[member.GlobalIndex] = value;
+ else
member.SetValue (ob, value);
- if (member.IsOptionalValueType)
- member.SetValueSpecified (ob, true);
- }
+ if (member.IsOptionalValueType)
+ member.SetValueSpecified (ob, true);
}
void SetMemberValueFromAttr (XmlTypeMapMember member, object ob, object value, bool isValueList)
return ReadObject (elem.MappedType, elem.IsNullable, true);
case SchemaTypes.XmlSerializable:
- object ob = Activator.CreateInstance (elem.TypeData.Type);
+ object ob = CreateInstance (elem.TypeData.Type, true);
return ReadSerializable ((IXmlSerializable)ob);
default:
else // Must be IEnumerable
{
if (list == null) {
- if (canCreateInstance) list = Activator.CreateInstance (type);
+ if (canCreateInstance) list = CreateInstance (type, true);
else throw CreateReadOnlyCollectionException (type.FullName);
}
}
}
+ static object CreateInstance (Type type, bool nonPublic)
+ {
+ return Activator.CreateInstance (type, nonPublic);
+ }
+
+ 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 CreateInstance (listType, true);
}
object InitializeList (TypeData listType)
if (listType.Type.IsArray)
return null;
else
- return Activator.CreateInstance (listType.Type);
+ return CreateInstance (listType.Type, true);
}
void FillList (object list, object items)
object GetEnumValue (XmlTypeMapping typeMap, string val)
{
+ if (val == null)
+ return null;
EnumMap map = (EnumMap) typeMap.ObjectMap;
string ev = map.GetEnumName (typeMap.TypeFullName, val);
if (ev == null) throw CreateUnknownConstantException (val, typeMap.TypeData.Type);
- return Enum.Parse (typeMap.TypeData.Type, ev);
+ return Enum.Parse (typeMap.TypeData.Type, ev, false);
}
object ReadXmlSerializableElement (XmlTypeMapping typeMap, bool isNullable)
Reader.MoveToContent ();
if (Reader.NodeType == XmlNodeType.Element)
{
- if (Reader.LocalName == typeMap.ElementName && Reader.NamespaceURI == typeMap.Namespace)
+ if (typeMap.IsAny || (Reader.LocalName == typeMap.ElementName && Reader.NamespaceURI == typeMap.Namespace))
{
- object ob = Activator.CreateInstance (typeMap.TypeData.Type);
+ object ob = CreateInstance (typeMap.TypeData.Type, true);
return ReadSerializable ((IXmlSerializable)ob);
}
else