1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //------------------------------------------------------------
5 namespace System
.Runtime
.Serialization
8 using System
.Collections
;
9 using System
.Diagnostics
;
10 using System
.Globalization
;
12 using System
.Reflection
;
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
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
);
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
);
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
;
376 if (IsRootXmlAny(rootName
, contract
))
377 throw DiagnosticUtility
.ExceptionUtility
.ThrowHelperError(XmlObjectSerializer
.CreateSerializationException(SR
.GetString(SR
.IsAnyCannotBeNull
, declaredType
)));
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
);
392 contract
.WriteXmlValue(writer
, graph
, null);
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
;
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
;
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()
509 internal static object SurrogateToDataContractType(IDataContractSurrogate dataContractSurrogate
, object oldObj
, Type surrogatedDeclaredType
, ref Type objType
)
511 object obj
= DataContractSurrogateCaller
.GetObjectToSerialize(dataContractSurrogate
, oldObj
, objType
, surrogatedDeclaredType
);
515 objType
= Globals
.TypeOfObject
;
517 objType
= obj
.GetType();
522 internal static Type
GetSurrogatedType(IDataContractSurrogate dataContractSurrogate
, Type type
)
524 return DataContractSurrogateCaller
.GetDataContractType(dataContractSurrogate
, DataContract
.UnwrapNullableType(type
));