Files
NetDataContractSerializer/Compat.Private.Serialization/Compat/Runtime/Serialization/XmlObjectSerializer.cs
2019-08-29 23:24:07 +03:00

419 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Xml;
using DataContractResolver = System.Runtime.Serialization.DataContractResolver;
using FormatterConverter = System.Runtime.Serialization.FormatterConverter;
using IFormatterConverter = System.Runtime.Serialization.IFormatterConverter;
using SerializationException = System.Runtime.Serialization.SerializationException;
namespace Compat.Runtime.Serialization
{
using DataContractDictionary = Dictionary<XmlQualifiedName, DataContract>;
public abstract class XmlObjectSerializer
{
public abstract void WriteStartObject(XmlDictionaryWriter writer, object graph);
public abstract void WriteObjectContent(XmlDictionaryWriter writer, object graph);
public abstract void WriteEndObject(XmlDictionaryWriter writer);
public virtual void WriteObject(Stream stream, object graph)
{
stream = stream ?? throw new ArgumentNullException(nameof(stream));
XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream: stream, encoding: Encoding.UTF8, ownsStream: false);
WriteObject(writer, graph);
writer.Flush();
}
public virtual void WriteObject(XmlWriter writer, object graph)
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
WriteObject(XmlDictionaryWriter.CreateDictionaryWriter(writer), graph);
}
public virtual void WriteStartObject(XmlWriter writer, object graph)
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
WriteStartObject(XmlDictionaryWriter.CreateDictionaryWriter(writer), graph);
}
public virtual void WriteObjectContent(XmlWriter writer, object graph)
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
WriteObjectContent(XmlDictionaryWriter.CreateDictionaryWriter(writer), graph);
}
public virtual void WriteEndObject(XmlWriter writer)
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
WriteEndObject(XmlDictionaryWriter.CreateDictionaryWriter(writer));
}
public virtual void WriteObject(XmlDictionaryWriter writer, object graph)
{
WriteObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
}
internal void WriteObjectHandleExceptions(XmlWriterDelegator writer, object graph)
{
WriteObjectHandleExceptions(writer, graph, null);
}
internal void WriteObjectHandleExceptions(XmlWriterDelegator writer, object graph, DataContractResolver dataContractResolver)
{
try
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
InternalWriteObject(writer, graph, dataContractResolver);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateSerializationException(GetTypeInfoError(SR.ErrorSerializing, GetSerializeType(graph), ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateSerializationException(GetTypeInfoError(SR.ErrorSerializing, GetSerializeType(graph), ex), ex));
}
}
internal virtual DataContractDictionary KnownDataContracts => null;
internal virtual void InternalWriteObject(XmlWriterDelegator writer, object graph)
{
WriteStartObject(writer.Writer, graph);
WriteObjectContent(writer.Writer, graph);
WriteEndObject(writer.Writer);
}
internal virtual void InternalWriteObject(XmlWriterDelegator writer, object graph, DataContractResolver dataContractResolver)
{
InternalWriteObject(writer, graph);
}
internal virtual void InternalWriteStartObject(XmlWriterDelegator writer, object graph)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
internal virtual void InternalWriteObjectContent(XmlWriterDelegator writer, object graph)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
internal virtual void InternalWriteEndObject(XmlWriterDelegator writer)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
internal void WriteStartObjectHandleExceptions(XmlWriterDelegator writer, object graph)
{
try
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
InternalWriteStartObject(writer, graph);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorWriteStartObject, GetSerializeType(graph), ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorWriteStartObject, GetSerializeType(graph), ex), ex));
}
}
internal void WriteObjectContentHandleExceptions(XmlWriterDelegator writer, object graph)
{
try
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
if (writer.WriteState != WriteState.Element)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.XmlWriterMustBeInElement, writer.WriteState)));
}
InternalWriteObjectContent(writer, graph);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorSerializing, GetSerializeType(graph), ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorSerializing, GetSerializeType(graph), ex), ex));
}
}
internal void WriteEndObjectHandleExceptions(XmlWriterDelegator writer)
{
try
{
writer = writer ?? throw new ArgumentNullException(nameof(writer));
InternalWriteEndObject(writer);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorWriteEndObject, null, ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorWriteEndObject, null, ex), ex));
}
}
internal void WriteRootElement(XmlWriterDelegator writer, DataContract contract, XmlDictionaryString name, XmlDictionaryString ns, bool needsContractNsAtRoot)
{
if (name == null) // root name not set explicitly
{
if (!contract.HasRoot)
{
return;
}
contract.WriteRootElement(writer, contract.TopLevelElementName, contract.TopLevelElementNamespace);
}
else
{
contract.WriteRootElement(writer, name, ns);
if (needsContractNsAtRoot)
{
writer.WriteNamespaceDecl(contract.Namespace);
}
}
}
internal bool CheckIfNeedsContractNsAtRoot(XmlDictionaryString name, XmlDictionaryString ns, DataContract contract)
{
if (name == null)
{
return false;
}
if (contract.IsBuiltInDataContract || !contract.CanContainReferences || contract.IsISerializable)
{
return false;
}
string contractNs = contract.Namespace?.Value;
if (string.IsNullOrEmpty(contractNs) || contractNs == ns?.Value)
{
return false;
}
return true;
}
internal static void WriteNull(XmlWriterDelegator writer)
{
writer.WriteAttributeBool(Globals.XsiPrefix, DictionaryGlobals.XsiNilLocalName, DictionaryGlobals.SchemaInstanceNamespace, true);
}
internal static bool IsContractDeclared(DataContract contract, DataContract declaredContract)
{
return (object.ReferenceEquals(contract.Name, declaredContract.Name) && object.ReferenceEquals(contract.Namespace, declaredContract.Namespace))
|| (contract.Name.Value == declaredContract.Name.Value && contract.Namespace.Value == declaredContract.Namespace.Value);
}
public virtual object ReadObject(Stream stream)
{
stream = stream ?? throw new ArgumentNullException(nameof(stream));
return ReadObject(XmlDictionaryReader.CreateTextReader(stream, XmlDictionaryReaderQuotas.Max));
}
public virtual object ReadObject(XmlReader reader)
{
reader = reader ?? throw new ArgumentNullException(nameof(reader));
return ReadObject(XmlDictionaryReader.CreateDictionaryReader(reader));
}
public virtual object ReadObject(XmlDictionaryReader reader)
{
return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), true /*verifyObjectName*/);
}
public virtual object ReadObject(XmlReader reader, bool verifyObjectName)
{
reader = reader ?? throw new ArgumentNullException(nameof(reader));
return ReadObject(XmlDictionaryReader.CreateDictionaryReader(reader), verifyObjectName);
}
public abstract object ReadObject(XmlDictionaryReader reader, bool verifyObjectName);
public virtual bool IsStartObject(XmlReader reader)
{
reader = reader ?? throw new ArgumentNullException(nameof(reader));
return IsStartObject(XmlDictionaryReader.CreateDictionaryReader(reader));
}
public abstract bool IsStartObject(XmlDictionaryReader reader);
internal virtual object InternalReadObject(XmlReaderDelegator reader, bool verifyObjectName)
{
return ReadObject(reader.UnderlyingReader, verifyObjectName);
}
internal virtual object InternalReadObject(XmlReaderDelegator reader, bool verifyObjectName, DataContractResolver dataContractResolver)
{
return InternalReadObject(reader, verifyObjectName);
}
internal virtual bool InternalIsStartObject(XmlReaderDelegator reader)
{
Fx.Assert("XmlObjectSerializer.InternalIsStartObject should never get called");
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
}
internal object ReadObjectHandleExceptions(XmlReaderDelegator reader, bool verifyObjectName)
{
return ReadObjectHandleExceptions(reader, verifyObjectName, null);
}
internal object ReadObjectHandleExceptions(XmlReaderDelegator reader, bool verifyObjectName, DataContractResolver dataContractResolver)
{
try
{
reader = reader ?? throw new ArgumentNullException(nameof(reader));
return InternalReadObject(reader, verifyObjectName, dataContractResolver);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorDeserializing, GetDeserializeType(), ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorDeserializing, GetDeserializeType(), ex), ex));
}
}
internal bool IsStartObjectHandleExceptions(XmlReaderDelegator reader)
{
try
{
reader = reader ?? throw new ArgumentNullException(nameof(reader));
return InternalIsStartObject(reader);
}
catch (XmlException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorIsStartObject, GetDeserializeType(), ex), ex));
}
catch (FormatException ex)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(GetTypeInfoError(SR.ErrorIsStartObject, GetDeserializeType(), ex), ex));
}
}
internal bool IsRootXmlAny(XmlDictionaryString rootName, DataContract contract)
{
return (rootName == null) && !contract.HasRoot;
}
internal bool IsStartElement(XmlReaderDelegator reader)
{
return (reader.MoveToElement() || reader.IsStartElement());
}
internal bool IsRootElement(XmlReaderDelegator reader, DataContract contract, XmlDictionaryString name, XmlDictionaryString ns)
{
reader.MoveToElement();
if (name != null) // root name set explicitly
{
return reader.IsStartElement(name, ns);
}
else
{
if (!contract.HasRoot)
{
return reader.IsStartElement();
}
if (reader.IsStartElement(contract.TopLevelElementName, contract.TopLevelElementNamespace))
{
return true;
}
ClassDataContract classContract = contract as ClassDataContract;
if (classContract != null)
{
classContract = classContract.BaseContract;
}
while (classContract != null)
{
if (reader.IsStartElement(classContract.TopLevelElementName, classContract.TopLevelElementNamespace))
{
return true;
}
classContract = classContract.BaseContract;
}
if (classContract == null)
{
DataContract objectContract = PrimitiveDataContract.GetPrimitiveDataContract(Globals.TypeOfObject);
if (reader.IsStartElement(objectContract.TopLevelElementName, objectContract.TopLevelElementNamespace))
{
return true;
}
}
return false;
}
}
internal static string TryAddLineInfo(XmlReaderDelegator reader, string errorMessage)
{
if (reader.HasLineInfo())
{
return string.Format(CultureInfo.InvariantCulture, "{0} {1}", SR.Format(SR.ErrorInLine, reader.LineNumber, reader.LinePosition), errorMessage);
}
return errorMessage;
}
internal static Exception CreateSerializationExceptionWithReaderDetails(string errorMessage, XmlReaderDelegator reader)
{
return XmlObjectSerializer.CreateSerializationException(TryAddLineInfo(reader, SR.Format(SR.EncounteredWithNameNamespace, errorMessage, reader.NodeType, reader.LocalName, reader.NamespaceURI)));
}
internal static SerializationException CreateSerializationException(string errorMessage)
{
return XmlObjectSerializer.CreateSerializationException(errorMessage, null);
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static SerializationException CreateSerializationException(string errorMessage, Exception innerException)
{
return new SerializationException(errorMessage, innerException);
}
private static string GetTypeInfoError(string errorMessage, Type type, Exception innerException)
{
string typeInfo = (type == null) ? string.Empty : SR.Format(SR.ErrorTypeInfo, DataContract.GetClrTypeFullName(type));
string innerExceptionMessage = innerException?.Message ?? string.Empty;
return SR.Format(errorMessage, typeInfo, innerExceptionMessage);
}
internal virtual Type GetSerializeType(object graph)
{
return graph?.GetType();
}
internal virtual Type GetDeserializeType()
{
return null;
}
private static IFormatterConverter formatterConverter;
internal static IFormatterConverter FormatterConverter
{
get
{
if (formatterConverter == null)
{
formatterConverter = new FormatterConverter();
}
return formatterConverter;
}
}
}
}