2016-08-03 10:59:49 +00:00
|
|
|
//------------------------------------------------------------
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
|
|
|
namespace System.Runtime.Serialization
|
|
|
|
{
|
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.Runtime.Diagnostics;
|
2016-11-10 13:04:39 +00:00
|
|
|
#if !MONO
|
2016-08-03 10:59:49 +00:00
|
|
|
using System.ServiceModel.Diagnostics;
|
2016-11-10 13:04:39 +00:00
|
|
|
#endif
|
2016-08-03 10:59:49 +00:00
|
|
|
using System.Text;
|
|
|
|
using System.Xml;
|
|
|
|
using System.Xml.Serialization;
|
|
|
|
using System.Runtime.Serialization.Diagnostics;
|
|
|
|
|
|
|
|
#if USE_REFEMIT
|
|
|
|
public class XmlObjectSerializerReadContext : XmlObjectSerializerContext
|
|
|
|
#else
|
|
|
|
internal class XmlObjectSerializerReadContext : XmlObjectSerializerContext
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
internal Attributes attributes;
|
|
|
|
HybridObjectCache deserializedObjects;
|
|
|
|
XmlSerializableReader xmlSerializableReader;
|
|
|
|
XmlDocument xmlDocument;
|
|
|
|
Attributes attributesInXmlData;
|
|
|
|
XmlReaderDelegator extensionDataReader;
|
|
|
|
object getOnlyCollectionValue;
|
|
|
|
bool isGetOnlyCollection;
|
|
|
|
|
|
|
|
HybridObjectCache DeserializedObjects
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (deserializedObjects == null)
|
|
|
|
deserializedObjects = new HybridObjectCache();
|
|
|
|
return deserializedObjects;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XmlDocument Document
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (xmlDocument == null)
|
|
|
|
xmlDocument = new XmlDocument();
|
|
|
|
return xmlDocument;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override bool IsGetOnlyCollection
|
|
|
|
{
|
|
|
|
get { return this.isGetOnlyCollection; }
|
|
|
|
set { this.isGetOnlyCollection = value; }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if USE_REFEMIT
|
|
|
|
public object GetCollectionMember()
|
|
|
|
#else
|
|
|
|
internal object GetCollectionMember()
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
return this.getOnlyCollectionValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if USE_REFEMIT
|
|
|
|
public void StoreCollectionMemberInfo(object collectionMember)
|
|
|
|
#else
|
|
|
|
internal void StoreCollectionMemberInfo(object collectionMember)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
this.getOnlyCollectionValue = collectionMember;
|
|
|
|
this.isGetOnlyCollection = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if USE_REFEMIT
|
|
|
|
public static void ThrowNullValueReturnedForGetOnlyCollectionException(Type type)
|
|
|
|
#else
|
|
|
|
internal static void ThrowNullValueReturnedForGetOnlyCollectionException(Type type)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.NullValueReturnedForGetOnlyCollection, DataContract.GetClrTypeFullName(type))));
|
|
|
|
}
|
|
|
|
|
|
|
|
#if USE_REFEMIT
|
|
|
|
public static void ThrowArrayExceededSizeException(int arraySize, Type type)
|
|
|
|
#else
|
|
|
|
internal static void ThrowArrayExceededSizeException(int arraySize, Type type)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArrayExceededSize, arraySize, DataContract.GetClrTypeFullName(type))));
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static XmlObjectSerializerReadContext CreateContext(DataContractSerializer serializer, DataContract rootTypeDataContract, DataContractResolver dataContractResolver)
|
|
|
|
{
|
|
|
|
return (serializer.PreserveObjectReferences || serializer.DataContractSurrogate != null)
|
|
|
|
? new XmlObjectSerializerReadContextComplex(serializer, rootTypeDataContract, dataContractResolver)
|
|
|
|
: new XmlObjectSerializerReadContext(serializer, rootTypeDataContract, dataContractResolver);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static XmlObjectSerializerReadContext CreateContext(NetDataContractSerializer serializer)
|
|
|
|
{
|
|
|
|
return new XmlObjectSerializerReadContextComplex(serializer);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal XmlObjectSerializerReadContext(XmlObjectSerializer serializer, int maxItemsInObjectGraph, StreamingContext streamingContext, bool ignoreExtensionDataObject)
|
|
|
|
: base(serializer, maxItemsInObjectGraph, streamingContext, ignoreExtensionDataObject)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
internal XmlObjectSerializerReadContext(DataContractSerializer serializer, DataContract rootTypeDataContract, DataContractResolver dataContractResolver)
|
|
|
|
: base(serializer, rootTypeDataContract, dataContractResolver)
|
|
|
|
{
|
|
|
|
this.attributes = new Attributes();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected XmlObjectSerializerReadContext(NetDataContractSerializer serializer)
|
|
|
|
: base(serializer)
|
|
|
|
{
|
|
|
|
this.attributes = new Attributes();
|
|
|
|
}
|
|
|
|
|
|
|
|
public virtual object InternalDeserialize(XmlReaderDelegator xmlReader, int id, RuntimeTypeHandle declaredTypeHandle, string name, string ns)
|
|
|
|
{
|
|
|
|
DataContract dataContract = GetDataContract(id, declaredTypeHandle);
|
|
|
|
return InternalDeserialize(xmlReader, name, ns, Type.GetTypeFromHandle(declaredTypeHandle), ref dataContract);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal virtual object InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, string name, string ns)
|
|
|
|
{
|
|
|
|
DataContract dataContract = GetDataContract(declaredType);
|
|
|
|
return InternalDeserialize(xmlReader, name, ns, declaredType, ref dataContract);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal virtual object InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, string name, string ns)
|
|
|
|
{
|
|
|
|
if (dataContract == null)
|
|
|
|
GetDataContract(declaredType);
|
|
|
|
return InternalDeserialize(xmlReader, name, ns, declaredType, ref dataContract);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected bool TryHandleNullOrRef(XmlReaderDelegator reader, Type declaredType, string name, string ns, ref object retObj)
|
|
|
|
{
|
|
|
|
ReadAttributes(reader);
|
|
|
|
|
|
|
|
if (attributes.Ref != Globals.NewObjectId)
|
|
|
|
{
|
|
|
|
if (this.isGetOnlyCollection)
|
|
|
|
{
|
|
|
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.IsReferenceGetOnlyCollectionsNotSupported, attributes.Ref, DataContract.GetClrTypeFullName(declaredType))));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
retObj = GetExistingObject(attributes.Ref, declaredType, name, ns);
|
|
|
|
reader.Skip();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (attributes.XsiNil)
|
|
|
|
{
|
|
|
|
reader.Skip();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected object InternalDeserialize(XmlReaderDelegator reader, string name, string ns, Type declaredType, ref DataContract dataContract)
|
|
|
|
{
|
|
|
|
object retObj = null;
|
|
|
|
if (TryHandleNullOrRef(reader, dataContract.UnderlyingType, name, ns, ref retObj))
|
|
|
|
return retObj;
|
|
|
|
|
|
|
|
bool knownTypesAddedInCurrentScope = false;
|
|
|
|
if (dataContract.KnownDataContracts != null)
|
|
|
|
{
|
|
|
|
scopedKnownTypes.Push(dataContract.KnownDataContracts);
|
|
|
|
knownTypesAddedInCurrentScope = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (attributes.XsiTypeName != null)
|
|
|
|
{
|
|
|
|
dataContract = ResolveDataContractFromKnownTypes(attributes.XsiTypeName, attributes.XsiTypeNamespace, dataContract, declaredType);
|
|
|
|
if (dataContract == null)
|
|
|
|
{
|
|
|
|
if (DataContractResolver == null)
|
|
|
|
{
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(XmlObjectSerializer.TryAddLineInfo(reader, SR.GetString(SR.DcTypeNotFoundOnDeserialize, attributes.XsiTypeNamespace, attributes.XsiTypeName, reader.NamespaceURI, reader.LocalName))));
|
|
|
|
}
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(XmlObjectSerializer.TryAddLineInfo(reader, SR.GetString(SR.DcTypeNotResolvedOnDeserialize, attributes.XsiTypeNamespace, attributes.XsiTypeName, reader.NamespaceURI, reader.LocalName))));
|
|
|
|
}
|
|
|
|
knownTypesAddedInCurrentScope = ReplaceScopedKnownTypesTop(dataContract.KnownDataContracts, knownTypesAddedInCurrentScope);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dataContract.IsISerializable && attributes.FactoryTypeName != null)
|
|
|
|
{
|
|
|
|
DataContract factoryDataContract = ResolveDataContractFromKnownTypes(attributes.FactoryTypeName, attributes.FactoryTypeNamespace, dataContract, declaredType);
|
|
|
|
if (factoryDataContract != null)
|
|
|
|
{
|
|
|
|
if (factoryDataContract.IsISerializable)
|
|
|
|
{
|
|
|
|
dataContract = factoryDataContract;
|
|
|
|
knownTypesAddedInCurrentScope = ReplaceScopedKnownTypesTop(dataContract.KnownDataContracts, knownTypesAddedInCurrentScope);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.FactoryTypeNotISerializable, DataContract.GetClrTypeFullName(factoryDataContract.UnderlyingType), DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (DiagnosticUtility.ShouldTraceWarning)
|
|
|
|
{
|
|
|
|
Dictionary<string, string> values = new Dictionary<string, string>(2);
|
|
|
|
values["FactoryType"] = attributes.FactoryTypeNamespace + ":" + attributes.FactoryTypeName;
|
|
|
|
values["ISerializableType"] = dataContract.StableName.Namespace + ":" + dataContract.StableName.Name;
|
|
|
|
TraceUtility.Trace(TraceEventType.Warning, TraceCode.FactoryTypeNotFound,
|
|
|
|
SR.GetString(SR.TraceCodeFactoryTypeNotFound), new DictionaryTraceRecord(values));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (knownTypesAddedInCurrentScope)
|
|
|
|
{
|
|
|
|
object obj = ReadDataContractValue(dataContract, reader);
|
|
|
|
scopedKnownTypes.Pop();
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return ReadDataContractValue(dataContract, reader);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReplaceScopedKnownTypesTop(Dictionary<XmlQualifiedName, DataContract> knownDataContracts, bool knownTypesAddedInCurrentScope)
|
|
|
|
{
|
|
|
|
if (knownTypesAddedInCurrentScope)
|
|
|
|
{
|
|
|
|
scopedKnownTypes.Pop();
|
|
|
|
knownTypesAddedInCurrentScope = false;
|
|
|
|
}
|
|
|
|
if (knownDataContracts != null)
|
|
|
|
{
|
|
|
|
scopedKnownTypes.Push(knownDataContracts);
|
|
|
|
knownTypesAddedInCurrentScope = true;
|
|
|
|
}
|
|
|
|
return knownTypesAddedInCurrentScope;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool MoveToNextElement(XmlReaderDelegator xmlReader)
|
|
|
|
{
|
|
|
|
return (xmlReader.MoveToContent() != XmlNodeType.EndElement);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int GetMemberIndex(XmlReaderDelegator xmlReader, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces, int memberIndex, ExtensionDataObject extensionData)
|
|
|
|
{
|
|
|
|
for (int i = memberIndex + 1; i < memberNames.Length; i++)
|
|
|
|
{
|
|
|
|
if (xmlReader.IsStartElement(memberNames[i], memberNamespaces[i]))
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
HandleMemberNotFound(xmlReader, extensionData, memberIndex);
|
|
|
|
return memberNames.Length;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int GetMemberIndexWithRequiredMembers(XmlReaderDelegator xmlReader, XmlDictionaryString[] memberNames, XmlDictionaryString[] memberNamespaces, int memberIndex, int requiredIndex, ExtensionDataObject extensionData)
|
|
|
|
{
|
|
|
|
for (int i = memberIndex + 1; i < memberNames.Length; i++)
|
|
|
|
{
|
|
|
|
if (xmlReader.IsStartElement(memberNames[i], memberNamespaces[i]))
|
|
|
|
{
|
|
|
|
if (requiredIndex < i)
|
|
|
|
ThrowRequiredMemberMissingException(xmlReader, memberIndex, requiredIndex, memberNames);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
HandleMemberNotFound(xmlReader, extensionData, memberIndex);
|
|
|
|
return memberNames.Length;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void ThrowRequiredMemberMissingException(XmlReaderDelegator xmlReader, int memberIndex, int requiredIndex, XmlDictionaryString[] memberNames)
|
|
|
|
{
|
|
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
|
|
if (requiredIndex == memberNames.Length)
|
|
|
|
requiredIndex--;
|
|
|
|
for (int i = memberIndex + 1; i <= requiredIndex; i++)
|
|
|
|
{
|
|
|
|
if (stringBuilder.Length != 0)
|
|
|
|
stringBuilder.Append(" | ");
|
|
|
|
stringBuilder.Append(memberNames[i].Value);
|
|
|
|
}
|
|
|
|
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(XmlObjectSerializer.TryAddLineInfo(xmlReader, SR.GetString(SR.UnexpectedElementExpectingElements, xmlReader.NodeType, xmlReader.LocalName, xmlReader.NamespaceURI, stringBuilder.ToString()))));
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void HandleMemberNotFound(XmlReaderDelegator xmlReader, ExtensionDataObject extensionData, int memberIndex)
|
|
|
|
{
|
|
|
|
xmlReader.MoveToContent();
|
|
|
|
if (xmlReader.NodeType != XmlNodeType.Element)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
|
|
|
|
|
|
|
|
if (IgnoreExtensionDataObject || extensionData == null)
|
|
|
|
SkipUnknownElement(xmlReader);
|
|
|
|
else
|
|
|
|
HandleUnknownElement(xmlReader, extensionData, memberIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void HandleUnknownElement(XmlReaderDelegator xmlReader, ExtensionDataObject extensionData, int memberIndex)
|
|
|
|
{
|
|
|
|
if (extensionData.Members == null)
|
|
|
|
extensionData.Members = new List<ExtensionDataMember>();
|
|
|
|
extensionData.Members.Add(ReadExtensionDataMember(xmlReader, memberIndex));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SkipUnknownElement(XmlReaderDelegator xmlReader)
|
|
|
|
{
|
|
|
|
ReadAttributes(xmlReader);
|
|
|
|
if (DiagnosticUtility.ShouldTraceVerbose)
|
|
|
|
{
|
|
|
|
TraceUtility.Trace(TraceEventType.Verbose, TraceCode.ElementIgnored,
|
|
|
|
SR.GetString(SR.TraceCodeElementIgnored), new StringTraceRecord("Element", xmlReader.NamespaceURI + ":" + xmlReader.LocalName));
|
|
|
|
}
|
|
|
|
xmlReader.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
public string ReadIfNullOrRef(XmlReaderDelegator xmlReader, Type memberType, bool isMemberTypeSerializable)
|
|
|
|
{
|
|
|
|
if (attributes.Ref != Globals.NewObjectId)
|
|
|
|
{
|
|
|
|
CheckIfTypeSerializable(memberType, isMemberTypeSerializable);
|
|
|
|
xmlReader.Skip();
|
|
|
|
return attributes.Ref;
|
|
|
|
}
|
|
|
|
else if (attributes.XsiNil)
|
|
|
|
{
|
|
|
|
CheckIfTypeSerializable(memberType, isMemberTypeSerializable);
|
|
|
|
xmlReader.Skip();
|
|
|
|
return Globals.NullObjectId;
|
|
|
|
}
|
|
|
|
return Globals.NewObjectId;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if USE_REFEMIT
|
|
|
|
public virtual void ReadAttributes(XmlReaderDelegator xmlReader)
|
|
|
|
#else
|
|
|
|
internal virtual void ReadAttributes(XmlReaderDelegator xmlReader)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
if (attributes == null)
|
|
|
|
attributes = new Attributes();
|
|
|
|
attributes.Read(xmlReader);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void ResetAttributes()
|
|
|
|
{
|
|
|
|
if (attributes != null)
|
|
|
|
attributes.Reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
public string GetObjectId()
|
|
|
|
{
|
|
|
|
return attributes.Id;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if USE_REFEMIT
|
|
|
|
public virtual int GetArraySize()
|
|
|
|
#else
|
|
|
|
internal virtual int GetArraySize()
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void AddNewObject(object obj)
|
|
|
|
{
|
|
|
|
AddNewObjectWithId(attributes.Id, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void AddNewObjectWithId(string id, object obj)
|
|
|
|
{
|
|
|
|
if (id != Globals.NewObjectId)
|
|
|
|
DeserializedObjects.Add(id, obj);
|
|
|
|
if (extensionDataReader != null)
|
|
|
|
extensionDataReader.UnderlyingExtensionDataReader.SetDeserializedValue(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void ReplaceDeserializedObject(string id, object oldObj, object newObj)
|
|
|
|
{
|
|
|
|
if (object.ReferenceEquals(oldObj, newObj))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (id != Globals.NewObjectId)
|
|
|
|
{
|
|
|
|
// In certain cases (IObjectReference, SerializationSurrogate or DataContractSurrogate),
|
|
|
|
// an object can be replaced with a different object once it is deserialized. If the
|
|
|
|
// object happens to be referenced from within itself, that reference needs to be updated
|
|
|
|
// with the new instance. BinaryFormatter supports this by fixing up such references later.
|
|
|
|
// These XmlObjectSerializer implementations do not currently support fix-ups. Hence we
|
|
|
|
// throw in such cases to allow us add fix-up support in the future if we need to.
|
|
|
|
if (DeserializedObjects.IsObjectReferenced(id))
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.FactoryObjectContainsSelfReference, DataContract.GetClrTypeFullName(oldObj.GetType()), DataContract.GetClrTypeFullName(newObj.GetType()), id)));
|
|
|
|
DeserializedObjects.Remove(id);
|
|
|
|
DeserializedObjects.Add(id, newObj);
|
|
|
|
}
|
|
|
|
if (extensionDataReader != null)
|
|
|
|
extensionDataReader.UnderlyingExtensionDataReader.SetDeserializedValue(newObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
public object GetExistingObject(string id, Type type, string name, string ns)
|
|
|
|
{
|
|
|
|
object retObj = DeserializedObjects.GetObject(id);
|
|
|
|
if (retObj == null)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.DeserializedObjectWithIdNotFound, id)));
|
|
|
|
if (retObj is IDataNode)
|
|
|
|
{
|
|
|
|
IDataNode dataNode = (IDataNode)retObj;
|
|
|
|
retObj = (dataNode.Value != null && dataNode.IsFinalValue) ? dataNode.Value : DeserializeFromExtensionData(dataNode, type, name, ns);
|
|
|
|
}
|
|
|
|
return retObj;
|
|
|
|
}
|
|
|
|
|
|
|
|
object GetExistingObjectOrExtensionData(string id)
|
|
|
|
{
|
|
|
|
object retObj = DeserializedObjects.GetObject(id);
|
|
|
|
if (retObj == null)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.DeserializedObjectWithIdNotFound, id)));
|
|
|
|
return retObj;
|
|
|
|
}
|
|
|
|
|
|
|
|
public object GetRealObject(IObjectReference obj, string id)
|
|
|
|
{
|
|
|
|
object realObj = SurrogateDataContract.GetRealObject(obj, this.GetStreamingContext());
|
|
|
|
// If GetRealObject returns null, it indicates that the object could not resolve itself because
|
|
|
|
// it is missing information. This may occur in a case where multiple IObjectReference instances
|
|
|
|
// depend on each other. BinaryFormatter supports this by fixing up the references later. These
|
|
|
|
// XmlObjectSerializer implementations do not support fix-ups since the format does not contain
|
|
|
|
// forward references. However, we throw for this case since it allows us to add fix-up support
|
|
|
|
// in the future if we need to.
|
|
|
|
if (realObj == null)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.GetRealObjectReturnedNull, DataContract.GetClrTypeFullName(obj.GetType()))));
|
|
|
|
ReplaceDeserializedObject(id, obj, realObj);
|
|
|
|
return realObj;
|
|
|
|
}
|
|
|
|
|
|
|
|
object DeserializeFromExtensionData(IDataNode dataNode, Type type, string name, string ns)
|
|
|
|
{
|
|
|
|
ExtensionDataReader underlyingExtensionDataReader;
|
|
|
|
if (extensionDataReader == null)
|
|
|
|
{
|
|
|
|
underlyingExtensionDataReader = new ExtensionDataReader(this);
|
|
|
|
extensionDataReader = CreateReaderDelegatorForReader(underlyingExtensionDataReader);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
underlyingExtensionDataReader = extensionDataReader.UnderlyingExtensionDataReader;
|
|
|
|
underlyingExtensionDataReader.SetDataNode(dataNode, name, ns);
|
|
|
|
object retObj = InternalDeserialize(extensionDataReader, type, name, ns);
|
|
|
|
dataNode.Clear();
|
|
|
|
underlyingExtensionDataReader.Reset();
|
|
|
|
return retObj;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void Read(XmlReaderDelegator xmlReader)
|
|
|
|
{
|
|
|
|
if (!xmlReader.Read())
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.UnexpectedEndOfFile)));
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static void ParseQualifiedName(string qname, XmlReaderDelegator xmlReader, out string name, out string ns, out string prefix)
|
|
|
|
{
|
|
|
|
int colon = qname.IndexOf(':');
|
|
|
|
prefix = "";
|
|
|
|
if (colon >= 0)
|
|
|
|
prefix = qname.Substring(0, colon);
|
|
|
|
name = qname.Substring(colon + 1);
|
|
|
|
ns = xmlReader.LookupNamespace(prefix);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static T[] EnsureArraySize<T>(T[] array, int index)
|
|
|
|
{
|
|
|
|
if (array.Length <= index)
|
|
|
|
{
|
|
|
|
if (index == Int32.MaxValue)
|
|
|
|
{
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
|
|
XmlObjectSerializer.CreateSerializationException(
|
|
|
|
SR.GetString(SR.MaxArrayLengthExceeded, Int32.MaxValue,
|
|
|
|
DataContract.GetClrTypeFullName(typeof(T)))));
|
|
|
|
}
|
|
|
|
int newSize = (index < Int32.MaxValue / 2) ? index * 2 : Int32.MaxValue;
|
|
|
|
T[] newArray = new T[newSize];
|
|
|
|
Array.Copy(array, 0, newArray, 0, array.Length);
|
|
|
|
array = newArray;
|
|
|
|
}
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static T[] TrimArraySize<T>(T[] array, int size)
|
|
|
|
{
|
|
|
|
if (size != array.Length)
|
|
|
|
{
|
|
|
|
T[] newArray = new T[size];
|
|
|
|
Array.Copy(array, 0, newArray, 0, size);
|
|
|
|
array = newArray;
|
|
|
|
}
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void CheckEndOfArray(XmlReaderDelegator xmlReader, int arraySize, XmlDictionaryString itemName, XmlDictionaryString itemNamespace)
|
|
|
|
{
|
|
|
|
if (xmlReader.NodeType == XmlNodeType.EndElement)
|
|
|
|
return;
|
|
|
|
while (xmlReader.IsStartElement())
|
|
|
|
{
|
|
|
|
if (xmlReader.IsStartElement(itemName, itemNamespace))
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArrayExceededSizeAttribute, arraySize, itemName.Value, itemNamespace.Value)));
|
|
|
|
SkipUnknownElement(xmlReader);
|
|
|
|
}
|
|
|
|
if (xmlReader.NodeType != XmlNodeType.EndElement)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.EndElement, xmlReader));
|
|
|
|
}
|
|
|
|
|
|
|
|
internal object ReadIXmlSerializable(XmlReaderDelegator xmlReader, XmlDataContract xmlDataContract, bool isMemberType)
|
|
|
|
{
|
|
|
|
if (xmlSerializableReader == null)
|
|
|
|
xmlSerializableReader = new XmlSerializableReader();
|
|
|
|
return ReadIXmlSerializable(xmlSerializableReader, xmlReader, xmlDataContract, isMemberType);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static object ReadRootIXmlSerializable(XmlReaderDelegator xmlReader, XmlDataContract xmlDataContract, bool isMemberType)
|
|
|
|
{
|
|
|
|
return ReadIXmlSerializable(new XmlSerializableReader(), xmlReader, xmlDataContract, isMemberType);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static object ReadIXmlSerializable(XmlSerializableReader xmlSerializableReader, XmlReaderDelegator xmlReader, XmlDataContract xmlDataContract, bool isMemberType)
|
|
|
|
{
|
|
|
|
object obj = null;
|
|
|
|
xmlSerializableReader.BeginRead(xmlReader);
|
|
|
|
if (isMemberType && !xmlDataContract.HasRoot)
|
|
|
|
{
|
|
|
|
xmlReader.Read();
|
|
|
|
xmlReader.MoveToContent();
|
|
|
|
}
|
|
|
|
if (xmlDataContract.UnderlyingType == Globals.TypeOfXmlElement)
|
|
|
|
{
|
|
|
|
if (!xmlReader.IsStartElement())
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
|
|
|
|
XmlDocument xmlDoc = new XmlDocument();
|
|
|
|
obj = (XmlElement)xmlDoc.ReadNode(xmlSerializableReader);
|
|
|
|
}
|
|
|
|
else if (xmlDataContract.UnderlyingType == Globals.TypeOfXmlNodeArray)
|
|
|
|
{
|
|
|
|
obj = XmlSerializableServices.ReadNodes(xmlSerializableReader);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IXmlSerializable xmlSerializable = xmlDataContract.CreateXmlSerializableDelegate();
|
|
|
|
xmlSerializable.ReadXml(xmlSerializableReader);
|
|
|
|
obj = xmlSerializable;
|
|
|
|
}
|
|
|
|
xmlSerializableReader.EndRead();
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
public SerializationInfo ReadSerializationInfo(XmlReaderDelegator xmlReader, Type type)
|
|
|
|
{
|
|
|
|
SerializationInfo serInfo = new SerializationInfo(type, XmlObjectSerializer.FormatterConverter);
|
|
|
|
XmlNodeType nodeType;
|
|
|
|
while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement)
|
|
|
|
{
|
|
|
|
if (nodeType != XmlNodeType.Element)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
|
|
|
|
|
|
|
|
if (xmlReader.NamespaceURI.Length != 0)
|
|
|
|
{
|
|
|
|
SkipUnknownElement(xmlReader);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
string name = XmlConvert.DecodeName(xmlReader.LocalName);
|
|
|
|
|
|
|
|
IncrementItemCount(1);
|
|
|
|
ReadAttributes(xmlReader);
|
|
|
|
object value;
|
|
|
|
if (attributes.Ref != Globals.NewObjectId)
|
|
|
|
{
|
|
|
|
xmlReader.Skip();
|
|
|
|
value = GetExistingObject(attributes.Ref, null, name, String.Empty);
|
|
|
|
}
|
|
|
|
else if (attributes.XsiNil)
|
|
|
|
{
|
|
|
|
xmlReader.Skip();
|
|
|
|
value = null;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value = InternalDeserialize(xmlReader, Globals.TypeOfObject, name, String.Empty);
|
|
|
|
}
|
|
|
|
|
|
|
|
serInfo.AddValue(name, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return serInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual DataContract ResolveDataContractFromTypeName()
|
|
|
|
{
|
|
|
|
return (attributes.XsiTypeName == null) ? null : ResolveDataContractFromKnownTypes(attributes.XsiTypeName, attributes.XsiTypeNamespace, null /*memberTypeContract*/, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExtensionDataMember ReadExtensionDataMember(XmlReaderDelegator xmlReader, int memberIndex)
|
|
|
|
{
|
|
|
|
ExtensionDataMember member = new ExtensionDataMember();
|
|
|
|
member.Name = xmlReader.LocalName;
|
|
|
|
member.Namespace = xmlReader.NamespaceURI;
|
|
|
|
member.MemberIndex = memberIndex;
|
|
|
|
if (xmlReader.UnderlyingExtensionDataReader != null)
|
|
|
|
{
|
|
|
|
// no need to re-read extension data structure
|
|
|
|
member.Value = xmlReader.UnderlyingExtensionDataReader.GetCurrentNode();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
member.Value = ReadExtensionDataValue(xmlReader);
|
|
|
|
return member;
|
|
|
|
}
|
|
|
|
|
|
|
|
public IDataNode ReadExtensionDataValue(XmlReaderDelegator xmlReader)
|
|
|
|
{
|
|
|
|
ReadAttributes(xmlReader);
|
|
|
|
IncrementItemCount(1);
|
|
|
|
IDataNode dataNode = null;
|
|
|
|
if (attributes.Ref != Globals.NewObjectId)
|
|
|
|
{
|
|
|
|
xmlReader.Skip();
|
|
|
|
object o = GetExistingObjectOrExtensionData(attributes.Ref);
|
|
|
|
dataNode = (o is IDataNode) ? (IDataNode)o : new DataNode<object>(o);
|
|
|
|
dataNode.Id = attributes.Ref;
|
|
|
|
}
|
|
|
|
else if (attributes.XsiNil)
|
|
|
|
{
|
|
|
|
xmlReader.Skip();
|
|
|
|
dataNode = null;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
string dataContractName = null;
|
|
|
|
string dataContractNamespace = null;
|
|
|
|
if (attributes.XsiTypeName != null)
|
|
|
|
{
|
|
|
|
dataContractName = attributes.XsiTypeName;
|
|
|
|
dataContractNamespace = attributes.XsiTypeNamespace;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsReadingCollectionExtensionData(xmlReader))
|
|
|
|
{
|
|
|
|
Read(xmlReader);
|
|
|
|
dataNode = ReadUnknownCollectionData(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
}
|
|
|
|
else if (attributes.FactoryTypeName != null)
|
|
|
|
{
|
|
|
|
Read(xmlReader);
|
|
|
|
dataNode = ReadUnknownISerializableData(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
}
|
|
|
|
else if (IsReadingClassExtensionData(xmlReader))
|
|
|
|
{
|
|
|
|
Read(xmlReader);
|
|
|
|
dataNode = ReadUnknownClassData(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DataContract dataContract = ResolveDataContractFromTypeName();
|
|
|
|
|
|
|
|
if (dataContract == null)
|
|
|
|
dataNode = ReadExtensionDataValue(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
else if (dataContract is XmlDataContract)
|
|
|
|
dataNode = ReadUnknownXmlData(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dataContract.IsISerializable)
|
|
|
|
{
|
|
|
|
Read(xmlReader);
|
|
|
|
dataNode = ReadUnknownISerializableData(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
}
|
|
|
|
else if (dataContract is PrimitiveDataContract)
|
|
|
|
{
|
|
|
|
if (attributes.Id == Globals.NewObjectId)
|
|
|
|
{
|
|
|
|
Read(xmlReader);
|
|
|
|
xmlReader.MoveToContent();
|
|
|
|
dataNode = ReadUnknownPrimitiveData(xmlReader, dataContract.UnderlyingType, dataContractName, dataContractNamespace);
|
|
|
|
xmlReader.ReadEndElement();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dataNode = new DataNode<object>(xmlReader.ReadElementContentAsAnyType(dataContract.UnderlyingType));
|
|
|
|
InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (dataContract is EnumDataContract)
|
|
|
|
{
|
|
|
|
dataNode = new DataNode<object>(((EnumDataContract)dataContract).ReadEnumValue(xmlReader));
|
|
|
|
InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
|
|
|
|
}
|
|
|
|
else if (dataContract is ClassDataContract)
|
|
|
|
{
|
|
|
|
Read(xmlReader);
|
|
|
|
dataNode = ReadUnknownClassData(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
}
|
|
|
|
else if (dataContract is CollectionDataContract)
|
|
|
|
{
|
|
|
|
Read(xmlReader);
|
|
|
|
dataNode = ReadUnknownCollectionData(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return dataNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual void StartReadExtensionDataValue(XmlReaderDelegator xmlReader)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
IDataNode ReadExtensionDataValue(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
|
|
|
|
{
|
|
|
|
StartReadExtensionDataValue(xmlReader);
|
|
|
|
|
|
|
|
if (attributes.UnrecognizedAttributesFound)
|
|
|
|
return ReadUnknownXmlData(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
|
|
|
|
IDictionary<string, string> namespacesInScope = xmlReader.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml);
|
|
|
|
Read(xmlReader);
|
|
|
|
xmlReader.MoveToContent();
|
|
|
|
|
|
|
|
switch (xmlReader.NodeType)
|
|
|
|
{
|
|
|
|
case XmlNodeType.Text:
|
|
|
|
return ReadPrimitiveExtensionDataValue(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
case XmlNodeType.Element:
|
|
|
|
if (xmlReader.NamespaceURI.StartsWith(Globals.DataContractXsdBaseNamespace, StringComparison.Ordinal))
|
|
|
|
return ReadUnknownClassData(xmlReader, dataContractName, dataContractNamespace);
|
|
|
|
else
|
|
|
|
return ReadAndResolveUnknownXmlData(xmlReader, namespacesInScope, dataContractName, dataContractNamespace);
|
|
|
|
|
|
|
|
case XmlNodeType.EndElement:
|
|
|
|
{
|
|
|
|
// NOTE: cannot distinguish between empty class or IXmlSerializable and typeof(object)
|
|
|
|
IDataNode objNode = ReadUnknownPrimitiveData(xmlReader, Globals.TypeOfObject, dataContractName, dataContractNamespace);
|
|
|
|
xmlReader.ReadEndElement();
|
|
|
|
objNode.IsFinalValue = false;
|
|
|
|
return objNode;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual IDataNode ReadPrimitiveExtensionDataValue(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
|
|
|
|
{
|
|
|
|
Type valueType = xmlReader.ValueType;
|
|
|
|
if (valueType == Globals.TypeOfString)
|
|
|
|
{
|
|
|
|
// NOTE: cannot distinguish other primitives from string (default XmlReader ValueType)
|
|
|
|
IDataNode stringNode = new DataNode<object>(xmlReader.ReadContentAsString());
|
|
|
|
InitializeExtensionDataNode(stringNode, dataContractName, dataContractNamespace);
|
|
|
|
stringNode.IsFinalValue = false;
|
|
|
|
xmlReader.ReadEndElement();
|
|
|
|
return stringNode;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IDataNode objNode = ReadUnknownPrimitiveData(xmlReader, valueType, dataContractName, dataContractNamespace);
|
|
|
|
xmlReader.ReadEndElement();
|
|
|
|
return objNode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void InitializeExtensionDataNode(IDataNode dataNode, string dataContractName, string dataContractNamespace)
|
|
|
|
{
|
|
|
|
dataNode.DataContractName = dataContractName;
|
|
|
|
dataNode.DataContractNamespace = dataContractNamespace;
|
|
|
|
dataNode.ClrAssemblyName = attributes.ClrAssembly;
|
|
|
|
dataNode.ClrTypeName = attributes.ClrType;
|
|
|
|
AddNewObject(dataNode);
|
|
|
|
dataNode.Id = attributes.Id;
|
|
|
|
}
|
|
|
|
|
|
|
|
IDataNode ReadUnknownPrimitiveData(XmlReaderDelegator xmlReader, Type type, string dataContractName, string dataContractNamespace)
|
|
|
|
{
|
|
|
|
IDataNode dataNode = xmlReader.ReadExtensionData(type);
|
|
|
|
InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
|
|
|
|
return dataNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassDataNode ReadUnknownClassData(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
|
|
|
|
{
|
|
|
|
ClassDataNode dataNode = new ClassDataNode();
|
|
|
|
InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
|
|
|
|
|
|
|
|
int memberIndex = 0;
|
|
|
|
XmlNodeType nodeType;
|
|
|
|
while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement)
|
|
|
|
{
|
|
|
|
if (nodeType != XmlNodeType.Element)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
|
|
|
|
|
|
|
|
if (dataNode.Members == null)
|
|
|
|
dataNode.Members = new List<ExtensionDataMember>();
|
|
|
|
dataNode.Members.Add(ReadExtensionDataMember(xmlReader, memberIndex++));
|
|
|
|
}
|
|
|
|
xmlReader.ReadEndElement();
|
|
|
|
return dataNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
CollectionDataNode ReadUnknownCollectionData(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
|
|
|
|
{
|
|
|
|
CollectionDataNode dataNode = new CollectionDataNode();
|
|
|
|
InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
|
|
|
|
|
|
|
|
int arraySize = attributes.ArraySZSize;
|
|
|
|
XmlNodeType nodeType;
|
|
|
|
while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement)
|
|
|
|
{
|
|
|
|
if (nodeType != XmlNodeType.Element)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
|
|
|
|
|
|
|
|
if (dataNode.ItemName == null)
|
|
|
|
{
|
|
|
|
dataNode.ItemName = xmlReader.LocalName;
|
|
|
|
dataNode.ItemNamespace = xmlReader.NamespaceURI;
|
|
|
|
}
|
|
|
|
if (xmlReader.IsStartElement(dataNode.ItemName, dataNode.ItemNamespace))
|
|
|
|
{
|
|
|
|
if (dataNode.Items == null)
|
|
|
|
dataNode.Items = new List<IDataNode>();
|
|
|
|
dataNode.Items.Add(ReadExtensionDataValue(xmlReader));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
SkipUnknownElement(xmlReader);
|
|
|
|
}
|
|
|
|
xmlReader.ReadEndElement();
|
|
|
|
|
|
|
|
if (arraySize != -1)
|
|
|
|
{
|
|
|
|
dataNode.Size = arraySize;
|
|
|
|
if (dataNode.Items == null)
|
|
|
|
{
|
|
|
|
if (dataNode.Size > 0)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArraySizeAttributeIncorrect, arraySize, 0)));
|
|
|
|
}
|
|
|
|
else if (dataNode.Size != dataNode.Items.Count)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArraySizeAttributeIncorrect, arraySize, dataNode.Items.Count)));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (dataNode.Items != null)
|
|
|
|
{
|
|
|
|
dataNode.Size = dataNode.Items.Count;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dataNode.Size = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return dataNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
ISerializableDataNode ReadUnknownISerializableData(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
|
|
|
|
{
|
|
|
|
ISerializableDataNode dataNode = new ISerializableDataNode();
|
|
|
|
InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
|
|
|
|
|
|
|
|
dataNode.FactoryTypeName = attributes.FactoryTypeName;
|
|
|
|
dataNode.FactoryTypeNamespace = attributes.FactoryTypeNamespace;
|
|
|
|
|
|
|
|
XmlNodeType nodeType;
|
|
|
|
while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement)
|
|
|
|
{
|
|
|
|
if (nodeType != XmlNodeType.Element)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateUnexpectedStateException(XmlNodeType.Element, xmlReader));
|
|
|
|
|
|
|
|
if (xmlReader.NamespaceURI.Length != 0)
|
|
|
|
{
|
|
|
|
SkipUnknownElement(xmlReader);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ISerializableDataMember member = new ISerializableDataMember();
|
|
|
|
member.Name = xmlReader.LocalName;
|
|
|
|
member.Value = ReadExtensionDataValue(xmlReader);
|
|
|
|
if (dataNode.Members == null)
|
|
|
|
dataNode.Members = new List<ISerializableDataMember>();
|
|
|
|
dataNode.Members.Add(member);
|
|
|
|
}
|
|
|
|
xmlReader.ReadEndElement();
|
|
|
|
return dataNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
IDataNode ReadUnknownXmlData(XmlReaderDelegator xmlReader, string dataContractName, string dataContractNamespace)
|
|
|
|
{
|
|
|
|
XmlDataNode dataNode = new XmlDataNode();
|
|
|
|
InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
|
|
|
|
dataNode.OwnerDocument = Document;
|
|
|
|
|
|
|
|
if (xmlReader.NodeType == XmlNodeType.EndElement)
|
|
|
|
return dataNode;
|
|
|
|
|
|
|
|
IList<XmlAttribute> xmlAttributes = null;
|
|
|
|
IList<XmlNode> xmlChildNodes = null;
|
|
|
|
|
|
|
|
XmlNodeType nodeType = xmlReader.MoveToContent();
|
|
|
|
if (nodeType != XmlNodeType.Text)
|
|
|
|
{
|
|
|
|
while (xmlReader.MoveToNextAttribute())
|
|
|
|
{
|
|
|
|
string ns = xmlReader.NamespaceURI;
|
|
|
|
if (ns != Globals.SerializationNamespace && ns != Globals.SchemaInstanceNamespace)
|
|
|
|
{
|
|
|
|
if (xmlAttributes == null)
|
|
|
|
xmlAttributes = new List<XmlAttribute>();
|
|
|
|
xmlAttributes.Add((XmlAttribute)Document.ReadNode(xmlReader.UnderlyingReader));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Read(xmlReader);
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((nodeType = xmlReader.MoveToContent()) != XmlNodeType.EndElement)
|
|
|
|
{
|
|
|
|
if (xmlReader.EOF)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.UnexpectedEndOfFile)));
|
|
|
|
|
|
|
|
if (xmlChildNodes == null)
|
|
|
|
xmlChildNodes = new List<XmlNode>();
|
|
|
|
xmlChildNodes.Add(Document.ReadNode(xmlReader.UnderlyingReader));
|
|
|
|
}
|
|
|
|
xmlReader.ReadEndElement();
|
|
|
|
|
|
|
|
dataNode.XmlAttributes = xmlAttributes;
|
|
|
|
dataNode.XmlChildNodes = xmlChildNodes;
|
|
|
|
return dataNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pattern-recognition logic: the method reads XML elements into DOM. To recognize as an array, it requires that
|
|
|
|
// all items have the same name and namespace. To recognize as an ISerializable type, it requires that all
|
|
|
|
// items be unqualified. If the XML only contains elements (no attributes or other nodes) is recognized as a
|
|
|
|
// class/class hierarchy. Otherwise it is deserialized as XML.
|
|
|
|
IDataNode ReadAndResolveUnknownXmlData(XmlReaderDelegator xmlReader, IDictionary<string, string> namespaces,
|
|
|
|
string dataContractName, string dataContractNamespace)
|
|
|
|
{
|
|
|
|
bool couldBeISerializableData = true;
|
|
|
|
bool couldBeCollectionData = true;
|
|
|
|
bool couldBeClassData = true;
|
|
|
|
string elementNs = null, elementName = null;
|
|
|
|
IList<XmlNode> xmlChildNodes = new List<XmlNode>();
|
|
|
|
IList<XmlAttribute> xmlAttributes = null;
|
|
|
|
if (namespaces != null)
|
|
|
|
{
|
|
|
|
xmlAttributes = new List<XmlAttribute>();
|
|
|
|
foreach (KeyValuePair<string, string> prefixNsPair in namespaces)
|
|
|
|
{
|
|
|
|
xmlAttributes.Add(AddNamespaceDeclaration(prefixNsPair.Key, prefixNsPair.Value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XmlNodeType nodeType;
|
|
|
|
while ((nodeType = xmlReader.NodeType) != XmlNodeType.EndElement)
|
|
|
|
{
|
|
|
|
if (nodeType == XmlNodeType.Element)
|
|
|
|
{
|
|
|
|
string ns = xmlReader.NamespaceURI;
|
|
|
|
string name = xmlReader.LocalName;
|
|
|
|
if (couldBeISerializableData)
|
|
|
|
couldBeISerializableData = (ns.Length == 0);
|
|
|
|
if (couldBeCollectionData)
|
|
|
|
{
|
|
|
|
if (elementName == null)
|
|
|
|
{
|
|
|
|
elementName = name;
|
|
|
|
elementNs = ns;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
couldBeCollectionData = (String.CompareOrdinal(elementName, name) == 0) &&
|
|
|
|
(String.CompareOrdinal(elementNs, ns) == 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (xmlReader.EOF)
|
|
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.UnexpectedEndOfFile)));
|
|
|
|
else if (IsContentNode(xmlReader.NodeType))
|
|
|
|
couldBeClassData = couldBeISerializableData = couldBeCollectionData = false;
|
|
|
|
|
|
|
|
if (attributesInXmlData == null) attributesInXmlData = new Attributes();
|
|
|
|
attributesInXmlData.Read(xmlReader);
|
|
|
|
|
|
|
|
XmlNode childNode = Document.ReadNode(xmlReader.UnderlyingReader);
|
|
|
|
xmlChildNodes.Add(childNode);
|
|
|
|
|
|
|
|
if (namespaces == null)
|
|
|
|
{
|
|
|
|
if (attributesInXmlData.XsiTypeName != null)
|
|
|
|
childNode.Attributes.Append(AddNamespaceDeclaration(attributesInXmlData.XsiTypePrefix, attributesInXmlData.XsiTypeNamespace));
|
|
|
|
if (attributesInXmlData.FactoryTypeName != null)
|
|
|
|
childNode.Attributes.Append(AddNamespaceDeclaration(attributesInXmlData.FactoryTypePrefix, attributesInXmlData.FactoryTypeNamespace));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
xmlReader.ReadEndElement();
|
|
|
|
|
|
|
|
if (elementName != null && couldBeCollectionData)
|
|
|
|
return ReadUnknownCollectionData(CreateReaderOverChildNodes(xmlAttributes, xmlChildNodes), dataContractName, dataContractNamespace);
|
|
|
|
else if (couldBeISerializableData)
|
|
|
|
return ReadUnknownISerializableData(CreateReaderOverChildNodes(xmlAttributes, xmlChildNodes), dataContractName, dataContractNamespace);
|
|
|
|
else if (couldBeClassData)
|
|
|
|
return ReadUnknownClassData(CreateReaderOverChildNodes(xmlAttributes, xmlChildNodes), dataContractName, dataContractNamespace);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
XmlDataNode dataNode = new XmlDataNode();
|
|
|
|
InitializeExtensionDataNode(dataNode, dataContractName, dataContractNamespace);
|
|
|
|
dataNode.OwnerDocument = Document;
|
|
|
|
dataNode.XmlChildNodes = xmlChildNodes;
|
|
|
|
dataNode.XmlAttributes = xmlAttributes;
|
|
|
|
return dataNode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsContentNode(XmlNodeType nodeType)
|
|
|
|
{
|
|
|
|
switch (nodeType)
|
|
|
|
{
|
|
|
|
case XmlNodeType.Whitespace:
|
|
|
|
case XmlNodeType.SignificantWhitespace:
|
|
|
|
case XmlNodeType.Comment:
|
|
|
|
case XmlNodeType.ProcessingInstruction:
|
|
|
|
case XmlNodeType.DocumentType:
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal XmlReaderDelegator CreateReaderOverChildNodes(IList<XmlAttribute> xmlAttributes, IList<XmlNode> xmlChildNodes)
|
|
|
|
{
|
|
|
|
XmlNode wrapperElement = CreateWrapperXmlElement(Document, xmlAttributes, xmlChildNodes, null, null, null);
|
|
|
|
XmlReaderDelegator nodeReader = CreateReaderDelegatorForReader(new XmlNodeReader(wrapperElement));
|
|
|
|
nodeReader.MoveToContent();
|
|
|
|
Read(nodeReader);
|
|
|
|
return nodeReader;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal static XmlNode CreateWrapperXmlElement(XmlDocument document, IList<XmlAttribute> xmlAttributes, IList<XmlNode> xmlChildNodes, string prefix, string localName, string ns)
|
|
|
|
{
|
|
|
|
localName = localName ?? "wrapper";
|
|
|
|
ns = ns ?? String.Empty;
|
|
|
|
XmlNode wrapperElement = document.CreateElement(prefix, localName, ns);
|
|
|
|
if (xmlAttributes != null)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < xmlAttributes.Count; i++)
|
|
|
|
wrapperElement.Attributes.Append((XmlAttribute)xmlAttributes[i]);
|
|
|
|
}
|
|
|
|
if (xmlChildNodes != null)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < xmlChildNodes.Count; i++)
|
|
|
|
wrapperElement.AppendChild(xmlChildNodes[i]);
|
|
|
|
}
|
|
|
|
return wrapperElement;
|
|
|
|
}
|
|
|
|
|
|
|
|
XmlAttribute AddNamespaceDeclaration(string prefix, string ns)
|
|
|
|
{
|
|
|
|
XmlAttribute attribute = (prefix == null || prefix.Length == 0) ?
|
|
|
|
Document.CreateAttribute(null, Globals.XmlnsPrefix, Globals.XmlnsNamespace) :
|
|
|
|
Document.CreateAttribute(Globals.XmlnsPrefix, prefix, Globals.XmlnsNamespace);
|
|
|
|
attribute.Value = ns;
|
|
|
|
return attribute;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Exception CreateUnexpectedStateException(XmlNodeType expectedState, XmlReaderDelegator xmlReader)
|
|
|
|
{
|
|
|
|
return XmlObjectSerializer.CreateSerializationExceptionWithReaderDetails(SR.GetString(SR.ExpectingState, expectedState), xmlReader);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual object ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader)
|
|
|
|
{
|
|
|
|
return dataContract.ReadXmlValue(reader, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual XmlReaderDelegator CreateReaderDelegatorForReader(XmlReader xmlReader)
|
|
|
|
{
|
|
|
|
return new XmlReaderDelegator(xmlReader);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual bool IsReadingCollectionExtensionData(XmlReaderDelegator xmlReader)
|
|
|
|
{
|
|
|
|
return (attributes.ArraySZSize != -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual bool IsReadingClassExtensionData(XmlReaderDelegator xmlReader)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|