[bcl] Updates referencesource to 4.7.1
[mono-project.git] / mcs / class / referencesource / System.Runtime.Serialization / System / Runtime / Serialization / DataContractSerializer.cs
blob6a6bb5100a8d108fbcca60c28d860588761230ee
1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System.Runtime.Serialization
7 using System;
8 using System.Collections;
9 using System.Diagnostics;
10 using System.Globalization;
11 using System.IO;
12 using System.Reflection;
13 using System.Text;
14 using System.Xml;
15 using System.Xml.Serialization;
16 using System.Collections.Generic;
17 using System.Collections.ObjectModel;
18 using System.Runtime.CompilerServices;
19 using DataContractDictionary = System.Collections.Generic.Dictionary<System.Xml.XmlQualifiedName, DataContract>;
21 public sealed class DataContractSerializer : XmlObjectSerializer
23 Type rootType;
24 DataContract rootContract; // post-surrogate
25 bool needsContractNsAtRoot;
26 XmlDictionaryString rootName;
27 XmlDictionaryString rootNamespace;
28 int maxItemsInObjectGraph;
29 bool ignoreExtensionDataObject;
30 bool preserveObjectReferences;
31 IDataContractSurrogate dataContractSurrogate;
32 ReadOnlyCollection<Type> knownTypeCollection;
33 internal IList<Type> knownTypeList;
34 internal DataContractDictionary knownDataContracts;
35 DataContractResolver dataContractResolver;
36 bool serializeReadOnlyTypes;
38 public DataContractSerializer(Type type)
39 : this(type, (IEnumerable<Type>)null)
43 public DataContractSerializer(Type type, IEnumerable<Type> knownTypes)
44 : this(type, knownTypes, int.MaxValue, false, false, null)
48 public DataContractSerializer(Type type,
49 IEnumerable<Type> knownTypes,
50 int maxItemsInObjectGraph,
51 bool ignoreExtensionDataObject,
52 bool preserveObjectReferences,
53 IDataContractSurrogate dataContractSurrogate)
54 : this(type, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, null)
58 public DataContractSerializer(Type type,
59 IEnumerable<Type> knownTypes,
60 int maxItemsInObjectGraph,
61 bool ignoreExtensionDataObject,
62 bool preserveObjectReferences,
63 IDataContractSurrogate dataContractSurrogate,
64 DataContractResolver dataContractResolver)
66 Initialize(type, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, dataContractResolver, false);
69 public DataContractSerializer(Type type, string rootName, string rootNamespace)
70 : this(type, rootName, rootNamespace, null)
74 public DataContractSerializer(Type type, string rootName, string rootNamespace, IEnumerable<Type> knownTypes)
75 : this(type, rootName, rootNamespace, knownTypes, int.MaxValue, false, false, null)
79 public DataContractSerializer(Type type, string rootName, string rootNamespace,
80 IEnumerable<Type> knownTypes,
81 int maxItemsInObjectGraph,
82 bool ignoreExtensionDataObject,
83 bool preserveObjectReferences,
84 IDataContractSurrogate dataContractSurrogate)
85 : this(type, rootName, rootNamespace, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, null)
89 public DataContractSerializer(Type type, string rootName, string rootNamespace,
90 IEnumerable<Type> knownTypes,
91 int maxItemsInObjectGraph,
92 bool ignoreExtensionDataObject,
93 bool preserveObjectReferences,
94 IDataContractSurrogate dataContractSurrogate,
95 DataContractResolver dataContractResolver)
97 XmlDictionary dictionary = new XmlDictionary(2);
98 Initialize(type, dictionary.Add(rootName), dictionary.Add(DataContract.GetNamespace(rootNamespace)), knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, dataContractResolver, false);
101 public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace)
102 : this(type, rootName, rootNamespace, null)
106 public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace, IEnumerable<Type> knownTypes)
107 : this(type, rootName, rootNamespace, knownTypes, int.MaxValue, false, false, null, null)
111 public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
112 IEnumerable<Type> knownTypes,
113 int maxItemsInObjectGraph,
114 bool ignoreExtensionDataObject,
115 bool preserveObjectReferences,
116 IDataContractSurrogate dataContractSurrogate)
117 : this(type, rootName, rootNamespace, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, null)
121 public DataContractSerializer(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
122 IEnumerable<Type> knownTypes,
123 int maxItemsInObjectGraph,
124 bool ignoreExtensionDataObject,
125 bool preserveObjectReferences,
126 IDataContractSurrogate dataContractSurrogate,
127 DataContractResolver dataContractResolver)
129 Initialize(type, rootName, rootNamespace, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, dataContractResolver, false);
132 public DataContractSerializer(Type type, DataContractSerializerSettings settings)
134 if (settings == null)
136 settings = new DataContractSerializerSettings();
138 Initialize(type, settings.RootName, settings.RootNamespace, settings.KnownTypes, settings.MaxItemsInObjectGraph, settings.IgnoreExtensionDataObject,
139 settings.PreserveObjectReferences, settings.DataContractSurrogate, settings.DataContractResolver, settings.SerializeReadOnlyTypes);
142 void Initialize(Type type,
143 IEnumerable<Type> knownTypes,
144 int maxItemsInObjectGraph,
145 bool ignoreExtensionDataObject,
146 bool preserveObjectReferences,
147 IDataContractSurrogate dataContractSurrogate,
148 DataContractResolver dataContractResolver,
149 bool serializeReadOnlyTypes)
151 CheckNull(type, "type");
152 this.rootType = type;
154 if (knownTypes != null)
156 this.knownTypeList = new List<Type>();
157 foreach (Type knownType in knownTypes)
159 this.knownTypeList.Add(knownType);
163 if (maxItemsInObjectGraph < 0)
164 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxItemsInObjectGraph", SR.GetString(SR.ValueMustBeNonNegative)));
165 this.maxItemsInObjectGraph = maxItemsInObjectGraph;
167 this.ignoreExtensionDataObject = ignoreExtensionDataObject;
168 this.preserveObjectReferences = preserveObjectReferences;
169 this.dataContractSurrogate = dataContractSurrogate;
170 this.dataContractResolver = dataContractResolver;
171 this.serializeReadOnlyTypes = serializeReadOnlyTypes;
174 void Initialize(Type type, XmlDictionaryString rootName, XmlDictionaryString rootNamespace,
175 IEnumerable<Type> knownTypes,
176 int maxItemsInObjectGraph,
177 bool ignoreExtensionDataObject,
178 bool preserveObjectReferences,
179 IDataContractSurrogate dataContractSurrogate,
180 DataContractResolver dataContractResolver,
181 bool serializeReadOnlyTypes)
183 Initialize(type, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, preserveObjectReferences, dataContractSurrogate, dataContractResolver, serializeReadOnlyTypes);
184 // validate root name and namespace are both non-null
185 this.rootName = rootName;
186 this.rootNamespace = rootNamespace;
189 public ReadOnlyCollection<Type> KnownTypes
193 if (knownTypeCollection == null)
195 if (knownTypeList != null)
197 knownTypeCollection = new ReadOnlyCollection<Type>(knownTypeList);
199 else
201 knownTypeCollection = new ReadOnlyCollection<Type>(Globals.EmptyTypeArray);
204 return knownTypeCollection;
208 internal override DataContractDictionary KnownDataContracts
212 if (this.knownDataContracts == null && this.knownTypeList != null)
214 // This assignment may be performed concurrently and thus is a race condition.
215 // It's safe, however, because at worse a new (and identical) dictionary of
216 // data contracts will be created and re-assigned to this field. Introduction
217 // of a lock here could lead to deadlocks.
218 this.knownDataContracts = XmlObjectSerializerContext.GetDataContractsForKnownTypes(this.knownTypeList);
220 return this.knownDataContracts;
224 public int MaxItemsInObjectGraph
226 get { return maxItemsInObjectGraph; }
229 public IDataContractSurrogate DataContractSurrogate
231 get { return dataContractSurrogate; }
234 public bool PreserveObjectReferences
236 get { return preserveObjectReferences; }
239 public bool IgnoreExtensionDataObject
241 get { return ignoreExtensionDataObject; }
244 public DataContractResolver DataContractResolver
246 get { return dataContractResolver; }
249 public bool SerializeReadOnlyTypes
251 get { return serializeReadOnlyTypes; }
254 DataContract RootContract
258 if (rootContract == null)
260 rootContract = DataContract.GetDataContract(((dataContractSurrogate == null) ? rootType : GetSurrogatedType(dataContractSurrogate, rootType)));
261 needsContractNsAtRoot = CheckIfNeedsContractNsAtRoot(rootName, rootNamespace, rootContract);
263 return rootContract;
267 internal override void InternalWriteObject(XmlWriterDelegator writer, object graph)
269 InternalWriteObject(writer, graph, null);
272 internal override void InternalWriteObject(XmlWriterDelegator writer, object graph, DataContractResolver dataContractResolver)
274 InternalWriteStartObject(writer, graph);
275 InternalWriteObjectContent(writer, graph, dataContractResolver);
276 InternalWriteEndObject(writer);
279 public override void WriteObject(XmlWriter writer, object graph)
281 WriteObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
284 public override void WriteStartObject(XmlWriter writer, object graph)
286 WriteStartObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
289 public override void WriteObjectContent(XmlWriter writer, object graph)
291 WriteObjectContentHandleExceptions(new XmlWriterDelegator(writer), graph);
294 public override void WriteEndObject(XmlWriter writer)
296 WriteEndObjectHandleExceptions(new XmlWriterDelegator(writer));
299 public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
301 WriteStartObjectHandleExceptions(new XmlWriterDelegator(writer), graph);
304 public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
306 WriteObjectContentHandleExceptions(new XmlWriterDelegator(writer), graph);
309 public override void WriteEndObject(XmlDictionaryWriter writer)
311 WriteEndObjectHandleExceptions(new XmlWriterDelegator(writer));
314 public void WriteObject(XmlDictionaryWriter writer, object graph, DataContractResolver dataContractResolver)
316 WriteObjectHandleExceptions(new XmlWriterDelegator(writer), graph, dataContractResolver);
319 public override object ReadObject(XmlReader reader)
321 return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), true /*verifyObjectName*/);
324 public override object ReadObject(XmlReader reader, bool verifyObjectName)
326 return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName);
329 public override bool IsStartObject(XmlReader reader)
331 return IsStartObjectHandleExceptions(new XmlReaderDelegator(reader));
334 public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
336 return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName);
339 public override bool IsStartObject(XmlDictionaryReader reader)
341 return IsStartObjectHandleExceptions(new XmlReaderDelegator(reader));
344 public object ReadObject(XmlDictionaryReader reader, bool verifyObjectName, DataContractResolver dataContractResolver)
346 return ReadObjectHandleExceptions(new XmlReaderDelegator(reader), verifyObjectName, dataContractResolver);
349 internal override void InternalWriteStartObject(XmlWriterDelegator writer, object graph)
351 WriteRootElement(writer, RootContract, rootName, rootNamespace, needsContractNsAtRoot);
354 internal override void InternalWriteObjectContent(XmlWriterDelegator writer, object graph)
356 InternalWriteObjectContent(writer, graph, null);
359 internal void InternalWriteObjectContent(XmlWriterDelegator writer, object graph, DataContractResolver dataContractResolver)
361 if (MaxItemsInObjectGraph == 0)
362 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
364 DataContract contract = RootContract;
365 Type declaredType = contract.UnderlyingType;
366 Type graphType = (graph == null) ? declaredType : graph.GetType();
368 if (dataContractSurrogate != null)
369 graph = SurrogateToDataContractType(dataContractSurrogate, graph, declaredType, ref graphType);
371 if (dataContractResolver == null)
372 dataContractResolver = this.DataContractResolver;
374 if (graph == null)
376 if (IsRootXmlAny(rootName, contract))
377 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.IsAnyCannotBeNull, declaredType)));
378 WriteNull(writer);
380 else
382 if (declaredType == graphType)
384 if (contract.CanContainReferences)
386 XmlObjectSerializerWriteContext context = XmlObjectSerializerWriteContext.CreateContext(this, contract, dataContractResolver);
387 context.HandleGraphAtTopLevel(writer, graph, contract);
388 context.SerializeWithoutXsiType(contract, writer, graph, declaredType.TypeHandle);
390 else
392 contract.WriteXmlValue(writer, graph, null);
395 else
397 XmlObjectSerializerWriteContext context = null;
398 if (IsRootXmlAny(rootName, contract))
399 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.IsAnyCannotBeSerializedAsDerivedType, graphType, contract.UnderlyingType)));
401 contract = GetDataContract(contract, declaredType, graphType);
402 context = XmlObjectSerializerWriteContext.CreateContext(this, RootContract, dataContractResolver);
403 if (contract.CanContainReferences)
405 context.HandleGraphAtTopLevel(writer, graph, contract);
407 context.OnHandleIsReference(writer, contract, graph);
408 context.SerializeWithXsiTypeAtTopLevel(contract, writer, graph, declaredType.TypeHandle, graphType);
413 internal static DataContract GetDataContract(DataContract declaredTypeContract, Type declaredType, Type objectType)
415 if (declaredType.IsInterface && CollectionDataContract.IsCollectionInterface(declaredType))
417 return declaredTypeContract;
419 else if (declaredType.IsArray)//Array covariance is not supported in XSD
421 return declaredTypeContract;
423 else
425 return DataContract.GetDataContract(objectType.TypeHandle, objectType, SerializationMode.SharedContract);
429 internal void SetDataContractSurrogate(IDataContractSurrogate adapter)
431 dataContractSurrogate = adapter;
434 internal override void InternalWriteEndObject(XmlWriterDelegator writer)
436 if (!IsRootXmlAny(rootName, RootContract))
438 writer.WriteEndElement();
442 internal override object InternalReadObject(XmlReaderDelegator xmlReader, bool verifyObjectName)
444 return InternalReadObject(xmlReader, verifyObjectName, null);
447 internal override object InternalReadObject(XmlReaderDelegator xmlReader, bool verifyObjectName, DataContractResolver dataContractResolver)
449 if (MaxItemsInObjectGraph == 0)
450 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ExceededMaxItemsQuota, MaxItemsInObjectGraph)));
452 if (dataContractResolver == null)
453 dataContractResolver = this.DataContractResolver;
455 if (verifyObjectName)
457 if (!InternalIsStartObject(xmlReader))
459 XmlDictionaryString expectedName;
460 XmlDictionaryString expectedNs;
461 if (rootName == null)
463 expectedName = RootContract.TopLevelElementName;
464 expectedNs = RootContract.TopLevelElementNamespace;
466 else
468 expectedName = rootName;
469 expectedNs = rootNamespace;
471 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationExceptionWithReaderDetails(SR.GetString(SR.ExpectingElement, expectedNs, expectedName), xmlReader));
474 else if (!IsStartElement(xmlReader))
476 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationExceptionWithReaderDetails(SR.GetString(SR.ExpectingElementAtDeserialize, XmlNodeType.Element), xmlReader));
479 DataContract contract = RootContract;
480 if (contract.IsPrimitive && object.ReferenceEquals(contract.UnderlyingType, rootType) /*handle Nullable<T> differently*/)
482 return contract.ReadXmlValue(xmlReader, null);
485 if (IsRootXmlAny(rootName, contract))
487 return XmlObjectSerializerReadContext.ReadRootIXmlSerializable(xmlReader, contract as XmlDataContract, false /*isMemberType*/);
490 XmlObjectSerializerReadContext context = XmlObjectSerializerReadContext.CreateContext(this, contract, dataContractResolver);
491 return context.InternalDeserialize(xmlReader, rootType, contract, null, null);
494 internal override bool InternalIsStartObject(XmlReaderDelegator reader)
496 return IsRootElement(reader, RootContract, rootName, rootNamespace);
499 internal override Type GetSerializeType(object graph)
501 return (graph == null) ? rootType : graph.GetType();
504 internal override Type GetDeserializeType()
506 return rootType;
509 internal static object SurrogateToDataContractType(IDataContractSurrogate dataContractSurrogate, object oldObj, Type surrogatedDeclaredType, ref Type objType)
511 object obj = DataContractSurrogateCaller.GetObjectToSerialize(dataContractSurrogate, oldObj, objType, surrogatedDeclaredType);
512 if (obj != oldObj)
514 if (obj == null)
515 objType = Globals.TypeOfObject;
516 else
517 objType = obj.GetType();
519 return obj;
522 internal static Type GetSurrogatedType(IDataContractSurrogate dataContractSurrogate, Type type)
524 return DataContractSurrogateCaller.GetDataContractType(dataContractSurrogate, DataContract.UnwrapNullableType(type));