2 // XmlSerializationReaderInterpreter.cs:
5 // Lluis Sanchez Gual (lluis@ximian.com)
7 // (C) 2002, 2003 Ximian, Inc. http://www.ximian.com
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System
.Reflection
;
33 using System
.Collections
;
35 namespace System
.Xml
.Serialization
37 internal class XmlSerializationReaderInterpreter
: XmlSerializationReader
40 SerializationFormat _format
;
41 static readonly XmlQualifiedName AnyType
= new XmlQualifiedName("anyType", System
.Xml
.Schema
.XmlSchema
.Namespace
);
42 static readonly object [] empty_array
= new object [0];
44 public XmlSerializationReaderInterpreter(XmlMapping typeMap
)
47 _format
= typeMap
.Format
;
50 protected override void InitCallbacks ()
52 ArrayList maps
= _typeMap
.RelatedMaps
;
55 foreach (XmlTypeMapping map
in maps
)
57 if (map
.TypeData
.SchemaType
== SchemaTypes
.Class
|| map
.TypeData
.SchemaType
== SchemaTypes
.Enum
)
59 ReaderCallbackInfo info
= new ReaderCallbackInfo (this, map
);
60 AddReadCallback (map
.XmlType
, map
.Namespace
, map
.TypeData
.Type
, new XmlSerializationReadCallback (info
.ReadObject
));
66 protected override void InitIDs ()
70 protected XmlTypeMapping
GetTypeMap (Type type
)
72 ArrayList maps
= _typeMap
.RelatedMaps
;
75 foreach (XmlTypeMapping map
in maps
)
76 if (map
.TypeData
.Type
== type
) return map
;
78 throw new InvalidOperationException ("Type " + type
+ " not mapped");
81 public object ReadRoot ()
83 Reader
.MoveToContent();
84 if (_typeMap
is XmlTypeMapping
)
86 if (_format
== SerializationFormat
.Literal
)
87 return ReadRoot ((XmlTypeMapping
)_typeMap
);
89 return ReadEncodedObject ((XmlTypeMapping
)_typeMap
);
92 return ReadMessage ((XmlMembersMapping
)_typeMap
);
95 object ReadEncodedObject (XmlTypeMapping typeMap
)
98 Reader
.MoveToContent();
99 if (Reader
.NodeType
== System
.Xml
.XmlNodeType
.Element
)
101 if (Reader
.LocalName
== typeMap
.ElementName
&& Reader
.NamespaceURI
== typeMap
.Namespace
)
102 ob
= ReadReferencedElement();
104 throw CreateUnknownNodeException();
109 ReadReferencedElements();
113 protected virtual object ReadMessage (XmlMembersMapping typeMap
)
115 object[] parameters
= new object[typeMap
.Count
];
117 if (typeMap
.HasWrapperElement
)
119 // bug #79988: out parameters need to be initialized if they
121 ArrayList members
= ((ClassMap
) typeMap
.ObjectMap
).AllMembers
;
122 for (int n
= 0; n
< members
.Count
; n
++) {
123 XmlTypeMapMember mem
= (XmlTypeMapMember
) members
[n
];
124 if (!mem
.IsReturnValue
&& mem
.TypeData
.IsValueType
)
125 SetMemberValueFromAttr (mem
, parameters
, CreateInstance (
126 mem
.TypeData
.Type
), true);
129 if (_format
== SerializationFormat
.Encoded
)
131 while (Reader
.NodeType
== System
.Xml
.XmlNodeType
.Element
)
133 string root
= Reader
.GetAttribute ("root", XmlSerializer
.EncodingNamespace
);
134 if (root
== null || System
.Xml
.XmlConvert
.ToBoolean(root
)) break;
135 ReadReferencedElement ();
136 Reader
.MoveToContent ();
140 while (Reader
.NodeType
!= System
.Xml
.XmlNodeType
.EndElement
&&
141 // it could be an empty root element
142 Reader
.ReadState
== ReadState
.Interactive
)
144 if (Reader
.IsStartElement(typeMap
.ElementName
, typeMap
.Namespace
)
145 || _format
== SerializationFormat
.Encoded
)
147 ReadAttributeMembers ((ClassMap
)typeMap
.ObjectMap
, parameters
, true);
148 if (Reader
.IsEmptyElement
) {
150 Reader
.MoveToContent();
153 Reader
.ReadStartElement();
154 ReadMembers ((ClassMap
)typeMap
.ObjectMap
, parameters
, true, false);
161 Reader
.MoveToContent();
165 ReadMembers ((ClassMap
)typeMap
.ObjectMap
, parameters
, true, _format
== SerializationFormat
.Encoded
);
167 if (_format
== SerializationFormat
.Encoded
)
168 ReadReferencedElements();
173 object ReadRoot (XmlTypeMapping rootMap
)
175 if (rootMap
.TypeData
.SchemaType
== SchemaTypes
.XmlNode
)
177 return ReadXmlNodeElement (rootMap
, true);
181 if (Reader
.LocalName
!= rootMap
.ElementName
|| Reader
.NamespaceURI
!= rootMap
.Namespace
)
182 throw CreateUnknownNodeException();
184 return ReadObject (rootMap
, rootMap
.IsNullable
, true);
189 protected virtual object ReadObject (XmlTypeMapping typeMap
, bool isNullable
, bool checkType
)
191 switch (typeMap
.TypeData
.SchemaType
)
193 case SchemaTypes
.Class
: return ReadClassInstance (typeMap
, isNullable
, checkType
);
194 case SchemaTypes
.Array
: return ReadListElement (typeMap
, isNullable
, null, true);
195 case SchemaTypes
.XmlNode
: return ReadXmlNodeElement (typeMap
, isNullable
);
196 case SchemaTypes
.Primitive
: return ReadPrimitiveElement (typeMap
, isNullable
);
197 case SchemaTypes
.Enum
: return ReadEnumElement (typeMap
, isNullable
);
198 case SchemaTypes
.XmlSerializable
: return ReadXmlSerializableElement (typeMap
, isNullable
);
199 default: throw new Exception ("Unsupported map type");
203 protected virtual object ReadClassInstance (XmlTypeMapping typeMap
, bool isNullable
, bool checkType
)
205 if (isNullable
&& ReadNull()) return null;
209 System
.Xml
.XmlQualifiedName t
= GetXsiType();
212 XmlTypeMapping realMap
= typeMap
.GetRealElementMap (t
.Name
, t
.Namespace
);
213 if (realMap
== null) {
214 if (typeMap
.TypeData
.Type
== typeof(object))
215 return ReadTypedPrimitive (t
);
217 throw CreateUnknownTypeException((System
.Xml
.XmlQualifiedName
)t
);
219 if (realMap
!= typeMap
)
220 return ReadObject (realMap
, false, false);
222 else if (typeMap
.TypeData
.Type
== typeof(object))
223 return ReadTypedPrimitive (AnyType
);
226 object ob
= Activator
.CreateInstance (typeMap
.TypeData
.Type
, true);
228 Reader
.MoveToElement();
229 bool isEmpty
= Reader
.IsEmptyElement
;
230 ReadClassInstanceMembers (typeMap
, ob
);
232 if (isEmpty
) Reader
.Skip();
233 else ReadEndElement();
238 protected virtual void ReadClassInstanceMembers (XmlTypeMapping typeMap
, object ob
)
240 ReadMembers ((ClassMap
) typeMap
.ObjectMap
, ob
, false, false);
243 void ReadAttributeMembers (ClassMap map
, object ob
, bool isValueList
)
245 XmlTypeMapMember anyAttrMember
= map
.DefaultAnyAttributeMember
;
246 int anyAttributeIndex
= 0;
247 object anyAttributeArray
= null;
249 while (Reader
.MoveToNextAttribute())
251 XmlTypeMapMemberAttribute member
= map
.GetAttribute (Reader
.LocalName
, Reader
.NamespaceURI
);
255 SetMemberValue (member
, ob
, GetValueFromXmlString (Reader
.Value
, member
.TypeData
, member
.MappedType
), isValueList
);
257 else if (IsXmlnsAttribute(Reader
.Name
))
259 // If the map has NamespaceDeclarations,
260 // then store this xmlns to the given member.
261 // If the instance doesn't exist, then create.
262 if (map
.NamespaceDeclarations
!= null) {
263 XmlSerializerNamespaces nss
= this.GetMemberValue (map
.NamespaceDeclarations
, ob
, isValueList
) as XmlSerializerNamespaces
;
265 nss
= new XmlSerializerNamespaces ();
266 SetMemberValue (map
.NamespaceDeclarations
, ob
, nss
, isValueList
);
268 if (Reader
.Prefix
== "xmlns")
269 nss
.Add (Reader
.LocalName
, Reader
.Value
);
271 nss
.Add ("", Reader
.Value
);
274 else if (anyAttrMember
!= null)
276 XmlAttribute attr
= (XmlAttribute
) Document
.ReadNode(Reader
);
277 ParseWsdlArrayType (attr
);
278 AddListValue (anyAttrMember
.TypeData
, ref anyAttributeArray
, anyAttributeIndex
++, attr
, true);
281 ProcessUnknownAttribute(ob
);
284 if (anyAttrMember
!= null)
286 anyAttributeArray
= ShrinkArray ((Array
)anyAttributeArray
, anyAttributeIndex
, anyAttrMember
.TypeData
.Type
.GetElementType(), true);
287 SetMemberValue (anyAttrMember
, ob
, anyAttributeArray
, isValueList
);
289 Reader
.MoveToElement ();
292 void ReadMembers (ClassMap map
, object ob
, bool isValueList
, bool readByOrder
)
295 ReadAttributeMembers (map
, ob
, isValueList
);
299 Reader
.MoveToElement();
300 if (Reader
.IsEmptyElement
) {
301 SetListMembersDefaults (map
, ob
, isValueList
);
305 Reader
.ReadStartElement();
310 bool[] readFlag
= new bool[(map
.ElementMembers
!= null) ? map
.ElementMembers
.Count
: 0];
312 bool hasAnyReturnMember
= (isValueList
&& _format
== SerializationFormat
.Encoded
&& map
.ReturnMember
!= null);
314 Reader
.MoveToContent();
316 int[] indexes
= null;
317 object[] flatLists
= null;
318 object[] flatListsChoices
= null;
324 if (map
.ElementMembers
!= null) maxInd
= map
.ElementMembers
.Count
;
328 maxInd
= int.MaxValue
;
330 if (map
.FlatLists
!= null)
332 indexes
= new int[map
.FlatLists
.Count
];
333 flatLists
= new object[map
.FlatLists
.Count
];
334 foreach (XmlTypeMapMemberExpandable mem
in map
.FlatLists
) {
335 if (IsReadOnly (mem
, mem
.TypeData
, ob
, isValueList
))
336 flatLists
[mem
.FlatArrayIndex
] = mem
.GetValue (ob
);
337 else if (mem
.TypeData
.Type
.IsArray
) {
338 flatLists
[mem
.FlatArrayIndex
] = InitializeList (mem
.TypeData
);
341 object list
= mem
.GetValue (ob
);
343 list
= InitializeList (mem
.TypeData
);
344 SetMemberValue (mem
, ob
, list
, isValueList
);
346 flatLists
[mem
.FlatArrayIndex
] = list
;
349 if (mem
.ChoiceMember
!= null) {
350 if (flatListsChoices
== null)
351 flatListsChoices
= new object [map
.FlatLists
.Count
];
352 flatListsChoices
[mem
.FlatArrayIndex
] = InitializeList (mem
.ChoiceTypeData
);
357 if (_format
== SerializationFormat
.Encoded
&& map
.ElementMembers
!= null)
359 FixupCallbackInfo info
= new FixupCallbackInfo (this, map
, isValueList
);
360 fixup
= new Fixup(ob
, new XmlSerializationFixupCallback(info
.FixupMembers
), map
.ElementMembers
.Count
);
364 while (Reader
.NodeType
!= System
.Xml
.XmlNodeType
.EndElement
&& (ind
< maxInd
))
366 if (Reader
.NodeType
== System
.Xml
.XmlNodeType
.Element
)
368 XmlTypeMapElementInfo info
;
371 info
= map
.GetElement (ind
++);
373 else if (hasAnyReturnMember
) {
374 info
= (XmlTypeMapElementInfo
) ((XmlTypeMapMemberElement
)map
.ReturnMember
).ElementInfo
[0];
375 hasAnyReturnMember
= false;
378 info
= map
.GetElement (Reader
.LocalName
, Reader
.NamespaceURI
);
380 if (info
!= null && !readFlag
[info
.Member
.Index
] )
382 if (info
.Member
.GetType() == typeof (XmlTypeMapMemberList
))
384 if (_format
== SerializationFormat
.Encoded
&& info
.MultiReferenceType
)
386 object list
= ReadReferencingElement (out fixup
.Ids
[info
.Member
.Index
]);
387 if (fixup
.Ids
[info
.Member
.Index
] == null) // Already read
389 if (IsReadOnly (info
.Member
, info
.TypeData
, ob
, isValueList
)) throw CreateReadOnlyCollectionException (info
.TypeData
.FullTypeName
);
390 else SetMemberValue (info
.Member
, ob
, list
, isValueList
);
392 else if (!info
.MappedType
.TypeData
.Type
.IsArray
)
394 if (IsReadOnly (info
.Member
, info
.TypeData
, ob
, isValueList
))
395 list
= GetMemberValue (info
.Member
, ob
, isValueList
);
397 list
= CreateList (info
.MappedType
.TypeData
.Type
);
398 SetMemberValue (info
.Member
, ob
, list
, isValueList
);
400 AddFixup (new CollectionFixup (list
, new XmlSerializationCollectionFixupCallback (FillList
), fixup
.Ids
[info
.Member
.Index
]));
401 fixup
.Ids
[info
.Member
.Index
] = null; // The member already has the value, no further fix needed.
406 if (IsReadOnly (info
.Member
, info
.TypeData
, ob
, isValueList
)) {
407 ReadListElement (info
.MappedType
, info
.IsNullable
, GetMemberValue (info
.Member
, ob
, isValueList
), false);
408 } else if (info
.MappedType
.TypeData
.Type
.IsArray
) {
409 object list
= ReadListElement (info
.MappedType
, info
.IsNullable
, null, true);
410 if (list
!= null || info
.IsNullable
)
411 SetMemberValue (info
.Member
, ob
, list
, isValueList
);
413 // If the member already has a list, reuse that list. No need to create a new one.
414 object list
= GetMemberValue (info
.Member
, ob
, isValueList
);
416 list
= CreateList (info
.MappedType
.TypeData
.Type
);
417 SetMemberValue (info
.Member
, ob
, list
, isValueList
);
419 ReadListElement (info
.MappedType
, info
.IsNullable
, list
, true);
422 readFlag
[info
.Member
.Index
] = true;
424 else if (info
.Member
.GetType() == typeof (XmlTypeMapMemberFlatList
))
426 XmlTypeMapMemberFlatList mem
= (XmlTypeMapMemberFlatList
)info
.Member
;
427 AddListValue (mem
.TypeData
, ref flatLists
[mem
.FlatArrayIndex
], indexes
[mem
.FlatArrayIndex
]++, ReadObjectElement (info
), !IsReadOnly (info
.Member
, info
.TypeData
, ob
, isValueList
));
428 if (mem
.ChoiceMember
!= null) {
429 AddListValue (mem
.ChoiceTypeData
, ref flatListsChoices
[mem
.FlatArrayIndex
], indexes
[mem
.FlatArrayIndex
]-1, info
.ChoiceValue
, true);
432 else if (info
.Member
.GetType() == typeof (XmlTypeMapMemberAnyElement
))
434 XmlTypeMapMemberAnyElement mem
= (XmlTypeMapMemberAnyElement
)info
.Member
;
435 if (mem
.TypeData
.IsListType
) AddListValue (mem
.TypeData
, ref flatLists
[mem
.FlatArrayIndex
], indexes
[mem
.FlatArrayIndex
]++, ReadXmlNode (mem
.TypeData
.ListItemTypeData
, false), true);
436 else SetMemberValue (mem
, ob
, ReadXmlNode (mem
.TypeData
, false), isValueList
);
438 else if (info
.Member
.GetType() == typeof(XmlTypeMapMemberElement
))
441 readFlag
[info
.Member
.Index
] = true;
442 if (_format
== SerializationFormat
.Encoded
)
444 if (info
.Member
.TypeData
.SchemaType
!= SchemaTypes
.Primitive
)
445 val
= ReadReferencingElement (out fixup
.Ids
[info
.Member
.Index
]);
447 val
= ReadReferencingElement (info
.Member
.TypeData
.XmlType
, System
.Xml
.Schema
.XmlSchema
.Namespace
, out fixup
.Ids
[info
.Member
.Index
]);
449 if (info
.MultiReferenceType
) {
450 if (fixup
.Ids
[info
.Member
.Index
] == null) // already read
451 SetMemberValue (info
.Member
, ob
, val
, isValueList
);
453 else if (val
!= null)
454 SetMemberValue (info
.Member
, ob
, val
, isValueList
);
457 SetMemberValue (info
.Member
, ob
, ReadObjectElement (info
), isValueList
);
458 if (info
.ChoiceValue
!= null) {
459 XmlTypeMapMemberElement imem
= (XmlTypeMapMemberElement
) info
.Member
;
460 imem
.SetChoice (ob
, info
.ChoiceValue
);
465 throw new InvalidOperationException ("Unknown member type");
467 else if (map
.DefaultAnyElementMember
!= null)
469 XmlTypeMapMemberAnyElement mem
= map
.DefaultAnyElementMember
;
470 if (mem
.TypeData
.IsListType
) AddListValue (mem
.TypeData
, ref flatLists
[mem
.FlatArrayIndex
], indexes
[mem
.FlatArrayIndex
]++, ReadXmlNode (mem
.TypeData
.ListItemTypeData
, false), true);
471 else SetMemberValue (mem
, ob
, ReadXmlNode (mem
.TypeData
, false), isValueList
);
474 ProcessUnknownElement(ob
);
476 else if ((Reader
.NodeType
== System
.Xml
.XmlNodeType
.Text
|| Reader
.NodeType
== System
.Xml
.XmlNodeType
.CDATA
) && map
.XmlTextCollector
!= null)
478 if (map
.XmlTextCollector
is XmlTypeMapMemberExpandable
)
480 XmlTypeMapMemberExpandable mem
= (XmlTypeMapMemberExpandable
)map
.XmlTextCollector
;
481 XmlTypeMapMemberFlatList flatl
= mem
as XmlTypeMapMemberFlatList
;
482 TypeData itype
= (flatl
== null) ? mem
.TypeData
.ListItemTypeData
: flatl
.ListMap
.FindTextElement().TypeData
;
484 object val
= (itype
.Type
== typeof (string)) ? (object) Reader
.ReadString() : (object) ReadXmlNode (itype
, false);
485 AddListValue (mem
.TypeData
, ref flatLists
[mem
.FlatArrayIndex
], indexes
[mem
.FlatArrayIndex
]++, val
, true);
489 XmlTypeMapMemberElement mem
= (XmlTypeMapMemberElement
) map
.XmlTextCollector
;
490 XmlTypeMapElementInfo info
= (XmlTypeMapElementInfo
) mem
.ElementInfo
[0];
491 if (info
.TypeData
.Type
== typeof (string))
492 SetMemberValue (mem
, ob
, ReadString ((string) GetMemberValue (mem
, ob
, isValueList
)), isValueList
);
494 SetMemberValue (mem
, ob
, GetValueFromXmlString (Reader
.ReadString(), info
.TypeData
, info
.MappedType
), isValueList
);
500 Reader
.MoveToContent();
503 if (flatLists
!= null)
505 foreach (XmlTypeMapMemberExpandable mem
in map
.FlatLists
)
507 Object list
= flatLists
[mem
.FlatArrayIndex
];
508 if (mem
.TypeData
.Type
.IsArray
)
509 list
= ShrinkArray ((Array
)list
, indexes
[mem
.FlatArrayIndex
], mem
.TypeData
.Type
.GetElementType(), true);
510 if (!IsReadOnly (mem
, mem
.TypeData
, ob
, isValueList
) && mem
.TypeData
.Type
.IsArray
)
511 SetMemberValue (mem
, ob
, list
, isValueList
);
515 if (flatListsChoices
!= null)
517 foreach (XmlTypeMapMemberExpandable mem
in map
.FlatLists
)
519 Object list
= flatListsChoices
[mem
.FlatArrayIndex
];
520 if (list
== null) continue;
521 list
= ShrinkArray ((Array
)list
, indexes
[mem
.FlatArrayIndex
], mem
.ChoiceTypeData
.Type
.GetElementType(), true);
522 XmlTypeMapMember
.SetValue (ob
, mem
.ChoiceMember
, list
);
525 SetListMembersDefaults (map
, ob
, isValueList
);
528 void SetListMembersDefaults (ClassMap map
, object ob
, bool isValueList
)
530 if (map
.ListMembers
!= null)
532 ArrayList members
= map
.ListMembers
;
533 for (int n
=0; n
<members
.Count
; n
++) {
534 XmlTypeMapMember mem
= (XmlTypeMapMember
) members
[n
];
535 if (IsReadOnly (mem
, mem
.TypeData
, ob
, isValueList
))
537 if (GetMemberValue (mem
, ob
, isValueList
) == null)
538 SetMemberValue (mem
, ob
, InitializeList (mem
.TypeData
), isValueList
);
543 internal void FixupMembers (ClassMap map
, object obfixup
, bool isValueList
)
545 Fixup fixup
= (Fixup
)obfixup
;
546 ICollection members
= map
.ElementMembers
;
547 string[] ids
= fixup
.Ids
;
548 foreach (XmlTypeMapMember member
in members
)
550 if (ids
[member
.Index
] != null)
551 SetMemberValue (member
, fixup
.Source
, GetTarget(ids
[member
.Index
]), isValueList
);
555 protected virtual void ProcessUnknownAttribute (object target
)
557 UnknownNode (target
);
560 protected virtual void ProcessUnknownElement (object target
)
562 UnknownNode (target
);
565 bool IsReadOnly (XmlTypeMapMember member
, TypeData memType
, object ob
, bool isValueList
)
567 if (isValueList
) return !memType
.HasPublicConstructor
;
568 else return member
.IsReadOnly (ob
.GetType()) || !memType
.HasPublicConstructor
;
571 void SetMemberValue (XmlTypeMapMember member
, object ob
, object value, bool isValueList
)
573 if (isValueList
) ((object[])ob
)[member
.GlobalIndex
] = value;
575 member
.SetValue (ob
, value);
576 if (member
.IsOptionalValueType
)
577 member
.SetValueSpecified (ob
, true);
581 void SetMemberValueFromAttr (XmlTypeMapMember member
, object ob
, object value, bool isValueList
)
583 // Enumeration values specified in custom attributes are stored as integer
584 // values if the custom attribute property is of type object. So, it is
585 // necessary to convert to the enum type before asigning the value to the field.
587 if (member
.TypeData
.Type
.IsEnum
)
588 value = Enum
.ToObject (member
.TypeData
.Type
, value);
589 SetMemberValue (member
, ob
, value, isValueList
);
592 object GetMemberValue (XmlTypeMapMember member
, object ob
, bool isValueList
)
594 if (isValueList
) return ((object[])ob
)[member
.GlobalIndex
];
595 else return member
.GetValue (ob
);
598 object ReadObjectElement (XmlTypeMapElementInfo elem
)
600 switch (elem
.TypeData
.SchemaType
)
602 case SchemaTypes
.XmlNode
:
603 return ReadXmlNode (elem
.TypeData
, true);
605 case SchemaTypes
.Primitive
:
606 case SchemaTypes
.Enum
:
607 return ReadPrimitiveValue (elem
);
609 case SchemaTypes
.Array
:
610 return ReadListElement (elem
.MappedType
, elem
.IsNullable
, null, true);
612 case SchemaTypes
.Class
:
613 return ReadObject (elem
.MappedType
, elem
.IsNullable
, true);
615 case SchemaTypes
.XmlSerializable
:
616 object ob
= Activator
.CreateInstance (elem
.TypeData
.Type
, true);
617 return ReadSerializable ((IXmlSerializable
)ob
);
620 throw new NotSupportedException ("Invalid value type");
624 object ReadPrimitiveValue (XmlTypeMapElementInfo elem
)
626 if (elem
.TypeData
.Type
== typeof (XmlQualifiedName
)) {
627 if (elem
.IsNullable
) return ReadNullableQualifiedName ();
628 else return ReadElementQualifiedName ();
630 else if (elem
.IsNullable
)
631 return GetValueFromXmlString (ReadNullableString (), elem
.TypeData
, elem
.MappedType
);
633 return GetValueFromXmlString (Reader
.ReadElementString (), elem
.TypeData
, elem
.MappedType
);
636 object GetValueFromXmlString (string value, TypeData typeData
, XmlTypeMapping typeMap
)
638 if (typeData
.SchemaType
== SchemaTypes
.Array
)
639 return ReadListString (typeMap
, value);
640 else if (typeData
.SchemaType
== SchemaTypes
.Enum
)
641 return GetEnumValue (typeMap
, value);
642 else if (typeData
.Type
== typeof (XmlQualifiedName
))
643 return ToXmlQualifiedName (value);
645 return XmlCustomFormatter
.FromXmlString (typeData
, value);
648 object ReadListElement (XmlTypeMapping typeMap
, bool isNullable
, object list
, bool canCreateInstance
)
650 Type listType
= typeMap
.TypeData
.Type
;
651 ListMap listMap
= (ListMap
)typeMap
.ObjectMap
;
653 if (listType
.IsArray
&& ReadNull()) return null;
656 if (canCreateInstance
&& typeMap
.TypeData
.HasPublicConstructor
) list
= CreateList (listType
);
657 else throw CreateReadOnlyCollectionException (typeMap
.TypeFullName
);
660 if (Reader
.IsEmptyElement
) {
662 if (listType
.IsArray
)
663 list
= ShrinkArray ((Array
)list
, 0, listType
.GetElementType(), false);
668 Reader
.ReadStartElement();
669 Reader
.MoveToContent();
671 while (Reader
.NodeType
!= System
.Xml
.XmlNodeType
.EndElement
)
673 if (Reader
.NodeType
== System
.Xml
.XmlNodeType
.Element
)
675 XmlTypeMapElementInfo elemInfo
= listMap
.FindElement (Reader
.LocalName
, Reader
.NamespaceURI
);
676 if (elemInfo
!= null)
677 AddListValue (typeMap
.TypeData
, ref list
, index
++, ReadObjectElement (elemInfo
), false);
684 Reader
.MoveToContent();
688 if (listType
.IsArray
)
689 list
= ShrinkArray ((Array
)list
, index
, listType
.GetElementType(), false);
694 object ReadListString (XmlTypeMapping typeMap
, string values
)
696 Type listType
= typeMap
.TypeData
.Type
;
697 ListMap listMap
= (ListMap
)typeMap
.ObjectMap
;
698 values
= values
.Trim ();
700 if (values
== string.Empty
)
702 return Array
.CreateInstance (listType
.GetElementType(), 0);
705 string[] valueArray
= values
.Split (' ');
706 Array list
= Array
.CreateInstance (listType
.GetElementType(), valueArray
.Length
);
708 XmlTypeMapElementInfo info
= (XmlTypeMapElementInfo
)listMap
.ItemInfo
[0];
710 for (int index
= 0; index
< valueArray
.Length
; index
++)
711 list
.SetValue (GetValueFromXmlString (valueArray
[index
], info
.TypeData
, info
.MappedType
), index
);
716 void AddListValue (TypeData listType
, ref object list
, int index
, object value, bool canCreateInstance
)
718 Type type
= listType
.Type
;
721 list
= EnsureArrayIndex ((Array
)list
, index
, type
.GetElementType());
722 ((Array
)list
).SetValue (value, index
);
724 else // Must be IEnumerable
727 if (canCreateInstance
) list
= Activator
.CreateInstance (type
, true);
728 else throw CreateReadOnlyCollectionException (type
.FullName
);
731 MethodInfo mi
= type
.GetMethod ("Add", new Type
[] {listType.ListItemType}
);
732 mi
.Invoke (list
, new object[] { value }
);
736 object CreateInstance (Type type
)
738 return Activator
.CreateInstance (type
, empty_array
);
741 object CreateList (Type listType
)
743 if (listType
.IsArray
)
744 return EnsureArrayIndex (null, 0, listType
.GetElementType());
746 return Activator
.CreateInstance (listType
, true);
749 object InitializeList (TypeData listType
)
751 if (listType
.Type
.IsArray
)
754 return Activator
.CreateInstance (listType
.Type
, true);
757 void FillList (object list
, object items
)
759 CopyEnumerableList (items
, list
);
762 void CopyEnumerableList (object source
, object dest
)
764 if (dest
== null) throw CreateReadOnlyCollectionException (source
.GetType().FullName
);
766 object[] param
= new object[1];
767 MethodInfo mi
= dest
.GetType().GetMethod ("Add");
768 foreach (object ob
in (IEnumerable
)source
)
771 mi
.Invoke (dest
, param
);
775 object ReadXmlNodeElement (XmlTypeMapping typeMap
, bool isNullable
)
777 return ReadXmlNode (typeMap
.TypeData
, false);
780 object ReadXmlNode (TypeData type
, bool wrapped
)
782 if (type
.Type
== typeof (XmlDocument
))
783 return ReadXmlDocument (wrapped
);
785 return ReadXmlNode (wrapped
);
788 object ReadPrimitiveElement (XmlTypeMapping typeMap
, bool isNullable
)
790 XmlQualifiedName t
= GetXsiType();
791 if (t
== null) t
= new XmlQualifiedName (typeMap
.XmlType
, typeMap
.Namespace
);
792 return ReadTypedPrimitive (t
);
795 object ReadEnumElement (XmlTypeMapping typeMap
, bool isNullable
)
797 Reader
.ReadStartElement ();
798 object o
= GetEnumValue (typeMap
, Reader
.ReadString());
803 object GetEnumValue (XmlTypeMapping typeMap
, string val
)
807 EnumMap map
= (EnumMap
) typeMap
.ObjectMap
;
808 string ev
= map
.GetEnumName (typeMap
.TypeFullName
, val
);
809 if (ev
== null) throw CreateUnknownConstantException (val
, typeMap
.TypeData
.Type
);
810 return Enum
.Parse (typeMap
.TypeData
.Type
, ev
);
813 object ReadXmlSerializableElement (XmlTypeMapping typeMap
, bool isNullable
)
815 Reader
.MoveToContent ();
816 if (Reader
.NodeType
== XmlNodeType
.Element
)
818 if (Reader
.LocalName
== typeMap
.ElementName
&& Reader
.NamespaceURI
== typeMap
.Namespace
)
820 object ob
= Activator
.CreateInstance (typeMap
.TypeData
.Type
, true);
821 return ReadSerializable ((IXmlSerializable
)ob
);
824 throw CreateUnknownNodeException ();
833 class FixupCallbackInfo
835 XmlSerializationReaderInterpreter _sri
;
839 public FixupCallbackInfo (XmlSerializationReaderInterpreter sri
, ClassMap map
, bool isValueList
)
843 _isValueList
= isValueList
;
846 public void FixupMembers (object fixup
)
848 _sri
.FixupMembers (_map
, fixup
, _isValueList
);
852 class ReaderCallbackInfo
854 XmlSerializationReaderInterpreter _sri
;
855 XmlTypeMapping _typeMap
;
857 public ReaderCallbackInfo (XmlSerializationReaderInterpreter sri
, XmlTypeMapping typeMap
)
863 internal object ReadObject ()
865 return _sri
.ReadObject (_typeMap
, true, true);