1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System.Runtime.Serialization
8 using System.Collections;
9 using System.Collections.Generic;
10 using System.Diagnostics;
11 using System.Runtime.Diagnostics;
13 using System.ServiceModel.Diagnostics;
17 using System.Xml.Serialization;
18 using System.Runtime.Serialization.Diagnostics;
21 public class XmlObjectSerializerReadContext : XmlObjectSerializerContext
23 internal class XmlObjectSerializerReadContext : XmlObjectSerializerContext
26 internal Attributes attributes;
27 HybridObjectCache deserializedObjects;
28 XmlSerializableReader xmlSerializableReader;
29 XmlDocument xmlDocument;
30 Attributes attributesInXmlData;
31 XmlReaderDelegator extensionDataReader;
32 object getOnlyCollectionValue;
33 bool isGetOnlyCollection;
35 HybridObjectCache DeserializedObjects
39 if (deserializedObjects == null)
40 deserializedObjects = new HybridObjectCache();
41 return deserializedObjects;
49 if (xmlDocument == null)
50 xmlDocument = new XmlDocument();
55 internal override bool IsGetOnlyCollection
57 get { return this.isGetOnlyCollection; }
58 set { this.isGetOnlyCollection = value; }
63 public object GetCollectionMember()
65 internal object GetCollectionMember()
68 return this.getOnlyCollectionValue;
72 public void StoreCollectionMemberInfo(object collectionMember)
74 internal void StoreCollectionMemberInfo(object collectionMember)
77 this.getOnlyCollectionValue = collectionMember;
78 this.isGetOnlyCollection = true;
82 public static void ThrowNullValueReturnedForGetOnlyCollectionException(Type type)
84 internal static void ThrowNullValueReturnedForGetOnlyCollectionException(Type type)
87 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.NullValueReturnedForGetOnlyCollection, DataContract.GetClrTypeFullName(type))));
91 public static void ThrowArrayExceededSizeException(int arraySize, Type type)
93 internal static void ThrowArrayExceededSizeException(int arraySize, Type type)
96 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArrayExceededSize, arraySize, DataContract.GetClrTypeFullName(type))));
99 internal static XmlObjectSerializerReadContext CreateContext(DataContractSerializer serializer, DataContract rootTypeDataContract, DataContractResolver dataContractResolver)
101 return (serializer.PreserveObjectReferences || serializer.DataContractSurrogate != null)
102 ? new XmlObjectSerializerReadContextComplex(serializer, rootTypeDataContract, dataContractResolver)
103 : new XmlObjectSerializerReadContext(serializer, rootTypeDataContract, dataContractResolver);
106 internal static XmlObjectSerializerReadContext CreateContext(NetDataContractSerializer serializer)
108 return new XmlObjectSerializerReadContextComplex(serializer);
111 internal XmlObjectSerializerReadContext(XmlObjectSerializer serializer, int maxItemsInObjectGraph, StreamingContext streamingContext, bool ignoreExtensionDataObject)
112 : base(serializer, maxItemsInObjectGraph, streamingContext, ignoreExtensionDataObject)
116 internal XmlObjectSerializerReadContext(DataContractSerializer serializer, DataContract rootTypeDataContract, DataContractResolver dataContractResolver)
117 : base(serializer, rootTypeDataContract, dataContractResolver)
119 this.attributes = new Attributes();
122 protected XmlObjectSerializerReadContext(NetDataContractSerializer serializer)
125 this.attributes = new Attributes();
128 public virtual object InternalDeserialize(XmlReaderDelegator xmlReader, int id, RuntimeTypeHandle declaredTypeHandle, string name, string ns)
130 DataContract dataContract = GetDataContract(id, declaredTypeHandle);
131 return InternalDeserialize(xmlReader, name, ns, Type.GetTypeFromHandle(declaredTypeHandle), ref dataContract);
134 internal virtual object InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, string name, string ns)
136 DataContract dataContract = GetDataContract(declaredType);
137 return InternalDeserialize(xmlReader, name, ns, declaredType, ref dataContract);
140 internal virtual object InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, string name, string ns)
142 if (dataContract == null)
143 GetDataContract(declaredType);
144 return InternalDeserialize(xmlReader, name, ns, declaredType, ref dataContract);
147 protected bool TryHandleNullOrRef(XmlReaderDelegator reader, Type declaredType, string name, string ns, ref object retObj)
149 ReadAttributes(reader);
151 if (attributes.Ref != Globals.NewObjectId)
153 if (this.isGetOnlyCollection)
155 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.IsReferenceGetOnlyCollectionsNotSupported, attributes.Ref, DataContract.GetClrTypeFullName(declaredType))));
159 retObj = GetExistingObject(attributes.Ref, declaredType, name, ns);
164 else if (attributes.XsiNil)
172 protected object InternalDeserialize(XmlReaderDelegator reader, string name, string ns, Type declaredType, ref DataContract dataContract)
174 object retObj = null;
175 if (TryHandleNullOrRef(reader, dataContract.UnderlyingType, name, ns, ref retObj))
178 bool knownTypesAddedInCurrentScope = false;
179 if (dataContract.KnownDataContracts != null)
181 scopedKnownTypes.Push(dataContract.KnownDataContracts);
182 knownTypesAddedInCurrentScope = true;
185 if (attributes.XsiTypeName != null)
187 dataContract = ResolveDataContractFromKnownTypes(attributes.XsiTypeName, attributes.XsiTypeNamespace, dataContract, declaredType);
188 if (dataContract == null)
190 if (DataContractResolver == null)
192 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(XmlObjectSerializer.TryAddLineInfo(reader, SR.GetString(SR.DcTypeNotFoundOnDeserialize, attributes.XsiTypeNamespace, attributes.XsiTypeName, reader.NamespaceURI, reader.LocalName))));
194 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(XmlObjectSerializer.TryAddLineInfo(reader, SR.GetString(SR.DcTypeNotResolvedOnDeserialize, attributes.XsiTypeNamespace, attributes.XsiTypeName, reader.NamespaceURI, reader.LocalName))));
196 knownTypesAddedInCurrentScope = ReplaceScopedKnownTypesTop(dataContract.KnownDataContracts, knownTypesAddedInCurrentScope);
199 if (dataContract.IsISerializable && attributes.FactoryTypeName != null)
201 DataContract factoryDataContract = ResolveDataContractFromKnownTypes(attributes.FactoryTypeName, attributes.FactoryTypeNamespace, dataContract, declaredType);
202 if (factoryDataContract != null)
204 if (factoryDataContract.IsISerializable)
206 dataContract = factoryDataContract;
207 knownTypesAddedInCurrentScope = ReplaceScopedKnownTypesTop(dataContract.KnownDataContracts, knownTypesAddedInCurrentScope);
210 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.FactoryTypeNotISerializable, DataContract.GetClrTypeFullName(factoryDataContract.UnderlyingType), DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
214 if (DiagnosticUtility.ShouldTraceWarning)
216 Dictionary<string, string> values = new Dictionary<string, string>(2);
217 values["FactoryType"] = attributes.FactoryTypeNamespace + ":" + attributes.FactoryTypeName;
218 values["ISerializableType"] = dataContract.StableName.Namespace + ":" + dataContract.StableName.Name;
219 TraceUtility.Trace(TraceEventType.Warning, TraceCode.FactoryTypeNotFound,
220 SR.GetString(SR.TraceCodeFactoryTypeNotFound), new DictionaryTraceRecord(values));
225 if (knownTypesAddedInCurrentScope)
227 object obj = ReadDataContractValue(dataContract, reader);
228 scopedKnownTypes.Pop();
233 return ReadDataContractValue(dataContract, reader);
237 bool ReplaceScopedKnownTypesTop(Dictionary<XmlQualifiedName, DataContract> knownDataContracts, bool knownTypesAddedInCurrentScope)
239 if (knownTypesAddedInCurrentScope)
241 scopedKnownTypes.Pop();
242 knownTypesAddedInCurrentScope = false;
244 if (knownDataContracts != null)
246 scopedKnownTypes.Push(knownDataContracts);
247 knownTypesAddedInCurrentScope = true;
249 return knownTypesAddedInCurrentScope;
252 public static bool MoveToNextElement(XmlReaderDelegator xmlReader)
254 return (xmlReader.MoveToContent() != XmlNodeType.EndElement);
257 public int GetMemberIndex(XmlReaderDelegator xmlReader, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces, int memberIndex, ExtensionDataObject extensionData)
259 for (int i = memberIndex + 1; i < memberNames.Length; i++)
261 if (xmlReader.IsStartElement(memberNames[i], memberNamespaces[i]))
264 HandleMemberNotFound(xmlReader, extensionData, memberIndex);
265 return memberNames.Length;
268 public int GetMemberIndexWithRequiredMembers(XmlReaderDelegator xmlReader, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces, int memberIndex, int requiredIndex, ExtensionDataObject extensionData)
270 for (int i = memberIndex + 1; i < memberNames.Length; i++)
272 if (xmlReader.IsStartElement(memberNames[i], memberNamespaces[i]))
274 if (requiredIndex < i)
275 ThrowRequiredMemberMissingException(xmlReader, memberIndex, requiredIndex, memberNames);
279 HandleMemberNotFound(xmlReader, extensionData, memberIndex);
280 return memberNames.Length;
283 public static void ThrowRequiredMemberMissingException(XmlReaderDelegator xmlReader, int memberIndex, int requiredIndex, XmlDictionaryString[] memberNames)
285 StringBuilder stringBuilder = new StringBuilder();
286 if (requiredIndex == memberNames.Length)
288 for (int i = memberIndex + 1; i <= requiredIndex; i++)
290 if (stringBuilder.Length != 0)
291 stringBuilder.Append(" | ");
292 stringBuilder.Append(memberNames[i].Value);
294 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(XmlObjectSerializer.TryAddLineInfo(xmlReader, SR.GetString(SR.UnexpectedElementExpectingElements, xmlReader.NodeType, xmlReader.LocalName, xmlReader.NamespaceURI, stringBuilder.ToString()))));
297 protected void HandleMemberNotFound(XmlReaderDelegator xmlReader, ExtensionDataObject extensionData, int memberIndex)
299 xmlReader.MoveToContent();
300 if (xmlReader.NodeType != XmlNodeType.Element)
301 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
303 if (IgnoreExtensionDataObject || extensionData == null)
304 SkipUnknownElement(xmlReader);
306 HandleUnknownElement(xmlReader, extensionData, memberIndex);
309 internal void HandleUnknownElement(XmlReaderDelegator xmlReader, ExtensionDataObject extensionData, int memberIndex)
311 if (extensionData.Members == null)
312 extensionData.Members = new List<ExtensionDataMember>();
313 extensionData.Members.Add(ReadExtensionDataMember(xmlReader, memberIndex));
316 public void SkipUnknownElement(XmlReaderDelegator xmlReader)
318 ReadAttributes(xmlReader);
319 if (DiagnosticUtility.ShouldTraceVerbose)
321 TraceUtility.Trace(TraceEventType.Verbose, TraceCode.ElementIgnored,
322 SR.GetString(SR.TraceCodeElementIgnored), new StringTraceRecord("Element", xmlReader.NamespaceURI + ":" + xmlReader.LocalName));
327 public string ReadIfNullOrRef(XmlReaderDelegator xmlReader, Type memberType, bool isMemberTypeSerializable)
329 if (attributes.Ref != Globals.NewObjectId)
331 CheckIfTypeSerializable(memberType, isMemberTypeSerializable);
333 return attributes.Ref;
335 else if (attributes.XsiNil)
337 CheckIfTypeSerializable(memberType, isMemberTypeSerializable);
339 return Globals.NullObjectId;
341 return Globals.NewObjectId;
345 public virtual void ReadAttributes(XmlReaderDelegator xmlReader)
347 internal virtual void ReadAttributes(XmlReaderDelegator xmlReader)
350 if (attributes == null)
351 attributes = new Attributes();
352 attributes.Read(xmlReader);
355 public void ResetAttributes()
357 if (attributes != null)
361 public string GetObjectId()
363 return attributes.Id;
367 public virtual int GetArraySize()
369 internal virtual int GetArraySize()
375 public void AddNewObject(object obj)
377 AddNewObjectWithId(attributes.Id, obj);
380 public void AddNewObjectWithId(string id, object obj)
382 if (id != Globals.NewObjectId)
383 DeserializedObjects.Add(id, obj);
384 if (extensionDataReader != null)
385 extensionDataReader.UnderlyingExtensionDataReader.SetDeserializedValue(obj);
388 public void ReplaceDeserializedObject(string id, object oldObj, object newObj)
390 if (object.ReferenceEquals(oldObj, newObj))
393 if (id != Globals.NewObjectId)
395 // In certain cases (IObjectReference, SerializationSurrogate or DataContractSurrogate),
396 // an object can be replaced with a different object once it is deserialized. If the
397 // object happens to be referenced from within itself, that reference needs to be updated
398 // with the new instance. BinaryFormatter supports this by fixing up such references later.
399 // These XmlObjectSerializer implementations do not currently support fix-ups. Hence we
400 // throw in such cases to allow us add fix-up support in the future if we need to.
401 if (DeserializedObjects.IsObjectReferenced(id))
402 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.FactoryObjectContainsSelfReference, DataContract.GetClrTypeFullName(oldObj.GetType()), DataContract.GetClrTypeFullName(newObj.GetType()), id)));
403 DeserializedObjects.Remove(id);
404 DeserializedObjects.Add(id, newObj);
406 if (extensionDataReader != null)
407 extensionDataReader.UnderlyingExtensionDataReader.SetDeserializedValue(newObj);
410 public object GetExistingObject(string id, Type type, string name, string ns)
412 object retObj = DeserializedObjects.GetObject(id);
414 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.DeserializedObjectWithIdNotFound, id)));
415 if (retObj is IDataNode)
417 IDataNode dataNode = (IDataNode)retObj;
418 retObj = (dataNode.Value != null && dataNode.IsFinalValue) ? dataNode.Value : DeserializeFromExtensionData(dataNode, type, name, ns);
423 object GetExistingObjectOrExtensionData(string id)
425 object retObj = DeserializedObjects.GetObject(id);
427 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.DeserializedObjectWithIdNotFound, id)));
431 public object GetRealObject(IObjectReference obj, string id)
433 object realObj = SurrogateDataContract.GetRealObject(obj, this.GetStreamingContext());
434 // If GetRealObject returns null, it indicates that the object could not resolve itself because
435 // it is missing information. This may occur in a case where multiple IObjectReference instances
436 // depend on each other. BinaryFormatter supports this by fixing up the references later. These
437 // XmlObjectSerializer implementations do not support fix-ups since the format does not contain
438 // forward references. However, we throw for this case since it allows us to add fix-up support
439 // in the future if we need to.
441 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.GetRealObjectReturnedNull, DataContract.GetClrTypeFullName(obj.GetType()))));
442 ReplaceDeserializedObject(id, obj, realObj);
446 object DeserializeFromExtensionData(IDataNode dataNode, Type type, string name, string ns)
448 ExtensionDataReader underlyingExtensionDataReader;
449 if (extensionDataReader == null)
451 underlyingExtensionDataReader = new ExtensionDataReader(this);
452 extensionDataReader = CreateReaderDelegatorForReader(underlyingExtensionDataReader);
455 underlyingExtensionDataReader = extensionDataReader.UnderlyingExtensionDataReader;
456 underlyingExtensionDataReader.SetDataNode(dataNode, name, ns);
457 object retObj = InternalDeserialize(extensionDataReader, type, name, ns);
459 underlyingExtensionDataReader.Reset();
463 public static void Read(XmlReaderDelegator xmlReader)
465 if (!xmlReader.Read())
466 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.UnexpectedEndOfFile)));
469 internal static void ParseQualifiedName(string qname, XmlReaderDelegator xmlReader, out string name, out string ns, out string prefix)
471 int colon = qname.IndexOf(':');
474 prefix = qname.Substring(0, colon);
475 name = qname.Substring(colon + 1);
476 ns = xmlReader.LookupNamespace(prefix);
479 public static T[] EnsureArraySize<T>(T[] array, int index)
481 if (array.Length <= index)
483 if (index == Int32.MaxValue)
485 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
486 XmlObjectSerializer.CreateSerializationException(
487 SR.GetString(SR.MaxArrayLengthExceeded, Int32.MaxValue,
488 DataContract.GetClrTypeFullName(typeof(T)))));
490 int newSize = (index < Int32.MaxValue / 2) ? index * 2 : Int32.MaxValue;
491 T[] newArray = new T[newSize];
492 Array.Copy(array, 0, newArray, 0, array.Length);
498 public static T[] TrimArraySize<T>(T[] array, int size)
500 if (size != array.Length)
502 T[] newArray = new T[size];
503 Array.Copy(array, 0, newArray, 0, size);
509 public void CheckEndOfArray(XmlReaderDelegator xmlReader, int arraySize, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
511 if (xmlReader.NodeType == XmlNodeType.EndElement)
513 while (xmlReader.IsStartElement())
515 if (xmlReader.IsStartElement(itemName, itemNamespace))
516 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArrayExceededSizeAttribute, arraySize, itemName.Value, itemNamespace.Value)));
517 SkipUnknownElement(xmlReader);
519 if (xmlReader.NodeType != XmlNodeType.EndElement)
520 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.EndElement, xmlReader));
523 internal object ReadIXmlSerializable(XmlReaderDelegator xmlReader, XmlDataContract xmlDataContract, bool isMemberType)
525 if (xmlSerializableReader == null)
526 xmlSerializableReader = new XmlSerializableReader();
527 return ReadIXmlSerializable(xmlSerializableReader, xmlReader, xmlDataContract, isMemberType);
530 internal static object ReadRootIXmlSerializable(XmlReaderDelegator xmlReader, XmlDataContract xmlDataContract, bool isMemberType)
532 return ReadIXmlSerializable(new XmlSerializableReader(), xmlReader, xmlDataContract, isMemberType);
535 internal static object ReadIXmlSerializable(XmlSerializableReader xmlSerializableReader, XmlReaderDelegator xmlReader, XmlDataContract xmlDataContract, bool isMemberType)
538 xmlSerializableReader.BeginRead(xmlReader);
539 if (isMemberType && !xmlDataContract.HasRoot)
542 xmlReader.MoveToContent();
544 if (xmlDataContract.UnderlyingType == Globals.TypeOfXmlElement)
546 if (!xmlReader.IsStartElement())
547 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
548 XmlDocument xmlDoc = new XmlDocument();
549 obj = (XmlElement)xmlDoc.ReadNode(xmlSerializableReader);
551 else if (xmlDataContract.UnderlyingType == Globals.TypeOfXmlNodeArray)
553 obj = XmlSerializableServices.ReadNodes(xmlSerializableReader);
557 IXmlSerializable xmlSerializable = xmlDataContract.CreateXmlSerializableDelegate();
558 xmlSerializable.ReadXml(xmlSerializableReader);
559 obj = xmlSerializable;
561 xmlSerializableReader.EndRead();
565 public SerializationInfo ReadSerializationInfo(XmlReaderDelegator xmlReader, Type type)
567 SerializationInfo serInfo = new SerializationInfo(type, XmlObjectSerializer.FormatterConverter);
568 XmlNodeType nodeType;
569 while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement)
571 if (nodeType != XmlNodeType.Element)
572 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
574 if (xmlReader.NamespaceURI.Length != 0)
576 SkipUnknownElement(xmlReader);
579 string name = XmlConvert.DecodeName(xmlReader.LocalName);
581 IncrementItemCount(1);
582 ReadAttributes(xmlReader);
584 if (attributes.Ref != Globals.NewObjectId)
587 value = GetExistingObject(attributes.Ref, null, name, String.Empty);
589 else if (attributes.XsiNil)
596 value = InternalDeserialize(xmlReader, Globals.TypeOfObject, name, String.Empty);
599 serInfo.AddValue(name, value);
605 protected virtual DataContract ResolveDataContractFromTypeName()
607 return (attributes.XsiTypeName == null) ? null : ResolveDataContractFromKnownTypes(attributes.XsiTypeName, attributes.XsiTypeNamespace, null /*memberTypeContract*/, null);
610 ExtensionDataMember ReadExtensionDataMember(XmlReaderDelegator xmlReader, int memberIndex)
612 ExtensionDataMember member = new ExtensionDataMember();
613 member.Name = xmlReader.LocalName;
614 member.Namespace = xmlReader.NamespaceURI;
615 member.MemberIndex = memberIndex;
616 if (xmlReader.UnderlyingExtensionDataReader != null)
618 // no need to re-read extension data structure
619 member.Value = xmlReader.UnderlyingExtensionDataReader.GetCurrentNode();
622 member.Value = ReadExtensionDataValue(xmlReader);
626 public IDataNode ReadExtensionDataValue(XmlReaderDelegator xmlReader)
628 ReadAttributes(xmlReader);
629 IncrementItemCount(1);
630 IDataNode dataNode = null;
631 if (attributes.Ref != Globals.NewObjectId)
634 object o = GetExistingObjectOrExtensionData(attributes.Ref);
635 dataNode = (o is IDataNode) ? (IDataNode)o : new DataNode<object>(o);
636 dataNode.Id = attributes.Ref;
638 else if (attributes.XsiNil)
645 string dataContractName = null;
646 string dataContractNamespace = null;
647 if (attributes.XsiTypeName != null)
649 dataContractName = attributes.XsiTypeName;
650 dataContractNamespace = attributes.XsiTypeNamespace;
653 if (IsReadingCollectionExtensionData(xmlReader))
656 dataNode = ReadUnknownCollectionData(xmlReader, dataContractName, dataContractNamespace);
658 else if (attributes.FactoryTypeName != null)
661 dataNode = ReadUnknownISerializableData(xmlReader, dataContractName, dataContractNamespace);
663 else if (IsReadingClassExtensionData(xmlReader))
666 dataNode = ReadUnknownClassData(xmlReader, dataContractName, dataContractNamespace);
670 DataContract dataContract = ResolveDataContractFromTypeName();
672 if (dataContract == null)
673 dataNode = ReadExtensionDataValue(xmlReader, dataContractName, dataContractNamespace);
674 else if (dataContract is XmlDataContract)
675 dataNode = ReadUnknownXmlData(xmlReader, dataContractName, dataContractNamespace);
678 if (dataContract.IsISerializable)
681 dataNode = ReadUnknownISerializableData(xmlReader, dataContractName, dataContractNamespace);
683 else if (dataContract is PrimitiveDataContract)
685 if (attributes.Id == Globals.NewObjectId)
688 xmlReader.MoveToContent();
689 dataNode = ReadUnknownPrimitiveData(xmlReader, dataContract.UnderlyingType, dataContractName, dataContractNamespace);
690 xmlReader.ReadEndElement();
694 dataNode = new DataNode<object>(xmlReader.ReadElementContentAsAnyType(dataContract.UnderlyingType));
695 InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
698 else if (dataContract is EnumDataContract)
700 dataNode = new DataNode<object>(((EnumDataContract)dataContract).ReadEnumValue(xmlReader));
701 InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
703 else if (dataContract is ClassDataContract)
706 dataNode = ReadUnknownClassData(xmlReader, dataContractName, dataContractNamespace);
708 else if (dataContract is CollectionDataContract)
711 dataNode = ReadUnknownCollectionData(xmlReader, dataContractName, dataContractNamespace);
719 protected virtual void StartReadExtensionDataValue(XmlReaderDelegator xmlReader)
723 IDataNode ReadExtensionDataValue(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
725 StartReadExtensionDataValue(xmlReader);
727 if (attributes.UnrecognizedAttributesFound)
728 return ReadUnknownXmlData(xmlReader, dataContractName, dataContractNamespace);
730 IDictionary<string, string> namespacesInScope = xmlReader.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml);
732 xmlReader.MoveToContent();
734 switch (xmlReader.NodeType)
736 case XmlNodeType.Text:
737 return ReadPrimitiveExtensionDataValue(xmlReader, dataContractName, dataContractNamespace);
738 case XmlNodeType.Element:
739 if (xmlReader.NamespaceURI.StartsWith(Globals.DataContractXsdBaseNamespace, StringComparison.Ordinal))
740 return ReadUnknownClassData(xmlReader, dataContractName, dataContractNamespace);
742 return ReadAndResolveUnknownXmlData(xmlReader, namespacesInScope, dataContractName, dataContractNamespace);
744 case XmlNodeType.EndElement:
746 // NOTE: cannot distinguish between empty class or IXmlSerializable and typeof(object)
747 IDataNode objNode = ReadUnknownPrimitiveData(xmlReader, Globals.TypeOfObject, dataContractName, dataContractNamespace);
748 xmlReader.ReadEndElement();
749 objNode.IsFinalValue = false;
753 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
757 protected virtual IDataNode ReadPrimitiveExtensionDataValue(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
759 Type valueType = xmlReader.ValueType;
760 if (valueType == Globals.TypeOfString)
762 // NOTE: cannot distinguish other primitives from string (default XmlReader ValueType)
763 IDataNode stringNode = new DataNode<object>(xmlReader.ReadContentAsString());
764 InitializeExtensionDataNode(stringNode, dataContractName, dataContractNamespace);
765 stringNode.IsFinalValue = false;
766 xmlReader.ReadEndElement();
771 IDataNode objNode = ReadUnknownPrimitiveData(xmlReader, valueType, dataContractName, dataContractNamespace);
772 xmlReader.ReadEndElement();
777 protected void InitializeExtensionDataNode(IDataNode dataNode, string dataContractName, string dataContractNamespace)
779 dataNode.DataContractName = dataContractName;
780 dataNode.DataContractNamespace = dataContractNamespace;
781 dataNode.ClrAssemblyName = attributes.ClrAssembly;
782 dataNode.ClrTypeName = attributes.ClrType;
783 AddNewObject(dataNode);
784 dataNode.Id = attributes.Id;
787 IDataNode ReadUnknownPrimitiveData(XmlReaderDelegator xmlReader, Type type, string dataContractName, string dataContractNamespace)
789 IDataNode dataNode = xmlReader.ReadExtensionData(type);
790 InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
794 ClassDataNode ReadUnknownClassData(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
796 ClassDataNode dataNode = new ClassDataNode();
797 InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
800 XmlNodeType nodeType;
801 while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement)
803 if (nodeType != XmlNodeType.Element)
804 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
806 if (dataNode.Members == null)
807 dataNode.Members = new List<ExtensionDataMember>();
808 dataNode.Members.Add(ReadExtensionDataMember(xmlReader, memberIndex++));
810 xmlReader.ReadEndElement();
814 CollectionDataNode ReadUnknownCollectionData(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
816 CollectionDataNode dataNode = new CollectionDataNode();
817 InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
819 int arraySize = attributes.ArraySZSize;
820 XmlNodeType nodeType;
821 while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement)
823 if (nodeType != XmlNodeType.Element)
824 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
826 if (dataNode.ItemName == null)
828 dataNode.ItemName = xmlReader.LocalName;
829 dataNode.ItemNamespace = xmlReader.NamespaceURI;
831 if (xmlReader.IsStartElement(dataNode.ItemName, dataNode.ItemNamespace))
833 if (dataNode.Items == null)
834 dataNode.Items = new List<IDataNode>();
835 dataNode.Items.Add(ReadExtensionDataValue(xmlReader));
838 SkipUnknownElement(xmlReader);
840 xmlReader.ReadEndElement();
844 dataNode.Size = arraySize;
845 if (dataNode.Items == null)
847 if (dataNode.Size > 0)
848 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArraySizeAttributeIncorrect, arraySize, 0)));
850 else if (dataNode.Size != dataNode.Items.Count)
851 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArraySizeAttributeIncorrect, arraySize, dataNode.Items.Count)));
855 if (dataNode.Items != null)
857 dataNode.Size = dataNode.Items.Count;
868 ISerializableDataNode ReadUnknownISerializableData(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
870 ISerializableDataNode dataNode = new ISerializableDataNode();
871 InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
873 dataNode.FactoryTypeName = attributes.FactoryTypeName;
874 dataNode.FactoryTypeNamespace = attributes.FactoryTypeNamespace;
876 XmlNodeType nodeType;
877 while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement)
879 if (nodeType != XmlNodeType.Element)
880 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
882 if (xmlReader.NamespaceURI.Length != 0)
884 SkipUnknownElement(xmlReader);
888 ISerializableDataMember member = new ISerializableDataMember();
889 member.Name = xmlReader.LocalName;
890 member.Value = ReadExtensionDataValue(xmlReader);
891 if (dataNode.Members == null)
892 dataNode.Members = new List<ISerializableDataMember>();
893 dataNode.Members.Add(member);
895 xmlReader.ReadEndElement();
899 IDataNode ReadUnknownXmlData(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
901 XmlDataNode dataNode = new XmlDataNode();
902 InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
903 dataNode.OwnerDocument = Document;
905 if (xmlReader.NodeType == XmlNodeType.EndElement)
908 IList<XmlAttribute> xmlAttributes = null;
909 IList<XmlNode> xmlChildNodes = null;
911 XmlNodeType nodeType = xmlReader.MoveToContent();
912 if (nodeType != XmlNodeType.Text)
914 while (xmlReader.MoveToNextAttribute())
916 string ns = xmlReader.NamespaceURI;
917 if (ns != Globals.SerializationNamespace && ns != Globals.SchemaInstanceNamespace)
919 if (xmlAttributes == null)
920 xmlAttributes = new List<XmlAttribute>();
921 xmlAttributes.Add((XmlAttribute)Document.ReadNode(xmlReader.UnderlyingReader));
927 while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement)
930 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.UnexpectedEndOfFile)));
932 if (xmlChildNodes == null)
933 xmlChildNodes = new List<XmlNode>();
934 xmlChildNodes.Add(Document.ReadNode(xmlReader.UnderlyingReader));
936 xmlReader.ReadEndElement();
938 dataNode.XmlAttributes = xmlAttributes;
939 dataNode.XmlChildNodes = xmlChildNodes;
943 // Pattern-recognition logic: the method reads XML elements into DOM. To recognize as an array, it requires that
944 // all items have the same name and namespace. To recognize as an ISerializable type, it requires that all
945 // items be unqualified. If the XML only contains elements (no attributes or other nodes) is recognized as a
946 // class/class hierarchy. Otherwise it is deserialized as XML.
947 IDataNode ReadAndResolveUnknownXmlData(XmlReaderDelegator xmlReader, IDictionary<string, string> namespaces,
948 string dataContractName, string dataContractNamespace)
950 bool couldBeISerializableData = true;
951 bool couldBeCollectionData = true;
952 bool couldBeClassData = true;
953 string elementNs = null, elementName = null;
954 IList<XmlNode> xmlChildNodes = new List<XmlNode>();
955 IList<XmlAttribute> xmlAttributes = null;
956 if (namespaces != null)
958 xmlAttributes = new List<XmlAttribute>();
959 foreach (KeyValuePair<string, string> prefixNsPair in namespaces)
961 xmlAttributes.Add(AddNamespaceDeclaration(prefixNsPair.Key, prefixNsPair.Value));
965 XmlNodeType nodeType;
966 while ((nodeType = xmlReader.NodeType) != XmlNodeType.EndElement)
968 if (nodeType == XmlNodeType.Element)
970 string ns = xmlReader.NamespaceURI;
971 string name = xmlReader.LocalName;
972 if (couldBeISerializableData)
973 couldBeISerializableData = (ns.Length == 0);
974 if (couldBeCollectionData)
976 if (elementName == null)
982 couldBeCollectionData = (String.CompareOrdinal(elementName, name) == 0) &&
983 (String.CompareOrdinal(elementNs, ns) == 0);
986 else if (xmlReader.EOF)
987 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.UnexpectedEndOfFile)));
988 else if (IsContentNode(xmlReader.NodeType))
989 couldBeClassData = couldBeISerializableData = couldBeCollectionData = false;
991 if (attributesInXmlData == null) attributesInXmlData = new Attributes();
992 attributesInXmlData.Read(xmlReader);
994 XmlNode childNode = Document.ReadNode(xmlReader.UnderlyingReader);
995 xmlChildNodes.Add(childNode);
997 if (namespaces == null)
999 if (attributesInXmlData.XsiTypeName != null)
1000 childNode.Attributes.Append(AddNamespaceDeclaration(attributesInXmlData.XsiTypePrefix, attributesInXmlData.XsiTypeNamespace));
1001 if (attributesInXmlData.FactoryTypeName != null)
1002 childNode.Attributes.Append(AddNamespaceDeclaration(attributesInXmlData.FactoryTypePrefix, attributesInXmlData.FactoryTypeNamespace));
1005 xmlReader.ReadEndElement();
1007 if (elementName != null && couldBeCollectionData)
1008 return ReadUnknownCollectionData(CreateReaderOverChildNodes(xmlAttributes, xmlChildNodes), dataContractName, dataContractNamespace);
1009 else if (couldBeISerializableData)
1010 return ReadUnknownISerializableData(CreateReaderOverChildNodes(xmlAttributes, xmlChildNodes), dataContractName, dataContractNamespace);
1011 else if (couldBeClassData)
1012 return ReadUnknownClassData(CreateReaderOverChildNodes(xmlAttributes, xmlChildNodes), dataContractName, dataContractNamespace);
1015 XmlDataNode dataNode = new XmlDataNode();
1016 InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
1017 dataNode.OwnerDocument = Document;
1018 dataNode.XmlChildNodes = xmlChildNodes;
1019 dataNode.XmlAttributes = xmlAttributes;
1024 bool IsContentNode(XmlNodeType nodeType)
1028 case XmlNodeType.Whitespace:
1029 case XmlNodeType.SignificantWhitespace:
1030 case XmlNodeType.Comment:
1031 case XmlNodeType.ProcessingInstruction:
1032 case XmlNodeType.DocumentType:
1039 internal XmlReaderDelegator CreateReaderOverChildNodes(IList<XmlAttribute> xmlAttributes, IList<XmlNode> xmlChildNodes)
1041 XmlNode wrapperElement = CreateWrapperXmlElement(Document, xmlAttributes, xmlChildNodes, null, null, null);
1042 XmlReaderDelegator nodeReader = CreateReaderDelegatorForReader(new XmlNodeReader(wrapperElement));
1043 nodeReader.MoveToContent();
1048 internal static XmlNode CreateWrapperXmlElement(XmlDocument document, IList<XmlAttribute> xmlAttributes, IList<XmlNode> xmlChildNodes, string prefix, string localName, string ns)
1050 localName = localName ?? "wrapper";
1051 ns = ns ?? String.Empty;
1052 XmlNode wrapperElement = document.CreateElement(prefix, localName, ns);
1053 if (xmlAttributes != null)
1055 for (int i = 0; i < xmlAttributes.Count; i++)
1056 wrapperElement.Attributes.Append((XmlAttribute)xmlAttributes[i]);
1058 if (xmlChildNodes != null)
1060 for (int i = 0; i < xmlChildNodes.Count; i++)
1061 wrapperElement.AppendChild(xmlChildNodes[i]);
1063 return wrapperElement;
1066 XmlAttribute AddNamespaceDeclaration(string prefix, string ns)
1068 XmlAttribute attribute = (prefix == null || prefix.Length == 0) ?
1069 Document.CreateAttribute(null, Globals.XmlnsPrefix, Globals.XmlnsNamespace) :
1070 Document.CreateAttribute(Globals.XmlnsPrefix, prefix, Globals.XmlnsNamespace);
1071 attribute.Value = ns;
1075 public static Exception CreateUnexpectedStateException(XmlNodeType expectedState, XmlReaderDelegator xmlReader)
1077 return XmlObjectSerializer.CreateSerializationExceptionWithReaderDetails(SR.GetString(SR.ExpectingState, expectedState), xmlReader);
1080 protected virtual object ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
1082 return dataContract.ReadXmlValue(reader, this);
1085 protected virtual XmlReaderDelegator CreateReaderDelegatorForReader(XmlReader xmlReader)
1087 return new XmlReaderDelegator(xmlReader);
1090 protected virtual bool IsReadingCollectionExtensionData(XmlReaderDelegator xmlReader)
1092 return (attributes.ArraySZSize != -1);
1095 protected virtual bool IsReadingClassExtensionData(XmlReaderDelegator xmlReader)