XmlObjectSerializerWriteContextComplex.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.Runtime.Serialization
  5. {
  6. using System;
  7. using System.Collections;
  8. using System.Diagnostics;
  9. using System.Globalization;
  10. using System.IO;
  11. using System.Reflection;
  12. using System.Text;
  13. using System.Xml;
  14. using System.Collections.Generic;
  15. using System.Security;
  16. using System.Security.Permissions;
  17. using System.Runtime.CompilerServices;
  18. using System.Runtime.Serialization.Diagnostics.Application;
  19. #if USE_REFEMIT
  20. public class XmlObjectSerializerWriteContextComplex : XmlObjectSerializerWriteContext
  21. #else
  22. internal class XmlObjectSerializerWriteContextComplex : XmlObjectSerializerWriteContext
  23. #endif
  24. {
  25. protected IDataContractSurrogate dataContractSurrogate;
  26. SerializationMode mode;
  27. SerializationBinder binder;
  28. ISurrogateSelector surrogateSelector;
  29. StreamingContext streamingContext;
  30. Hashtable surrogateDataContracts;
  31. internal XmlObjectSerializerWriteContextComplex(DataContractSerializer serializer, DataContract rootTypeDataContract, DataContractResolver dataContractResolver)
  32. : base(serializer, rootTypeDataContract, dataContractResolver)
  33. {
  34. this.mode = SerializationMode.SharedContract;
  35. this.preserveObjectReferences = serializer.PreserveObjectReferences;
  36. this.dataContractSurrogate = serializer.DataContractSurrogate;
  37. }
  38. internal XmlObjectSerializerWriteContextComplex(NetDataContractSerializer serializer, Hashtable surrogateDataContracts)
  39. : base(serializer)
  40. {
  41. this.mode = SerializationMode.SharedType;
  42. this.preserveObjectReferences = true;
  43. this.streamingContext = serializer.Context;
  44. this.binder = serializer.Binder;
  45. this.surrogateSelector = serializer.SurrogateSelector;
  46. this.surrogateDataContracts = surrogateDataContracts;
  47. }
  48. internal XmlObjectSerializerWriteContextComplex(XmlObjectSerializer serializer, int maxItemsInObjectGraph, StreamingContext streamingContext, bool ignoreExtensionDataObject)
  49. : base(serializer, maxItemsInObjectGraph, streamingContext, ignoreExtensionDataObject)
  50. {
  51. }
  52. internal override SerializationMode Mode
  53. {
  54. get { return mode; }
  55. }
  56. internal override DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type type)
  57. {
  58. DataContract dataContract = null;
  59. if (mode == SerializationMode.SharedType && surrogateSelector != null)
  60. {
  61. dataContract = NetDataContractSerializer.GetDataContractFromSurrogateSelector(surrogateSelector, streamingContext, typeHandle, type, ref surrogateDataContracts);
  62. }
  63. if (dataContract != null)
  64. {
  65. if (this.IsGetOnlyCollection && dataContract is SurrogateDataContract)
  66. {
  67. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
  68. DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
  69. }
  70. return dataContract;
  71. }
  72. return base.GetDataContract(typeHandle, type);
  73. }
  74. internal override DataContract GetDataContract(int id, RuntimeTypeHandle typeHandle)
  75. {
  76. DataContract dataContract = null;
  77. if (mode == SerializationMode.SharedType && surrogateSelector != null)
  78. {
  79. dataContract = NetDataContractSerializer.GetDataContractFromSurrogateSelector(surrogateSelector, streamingContext, typeHandle, null /*type*/, ref surrogateDataContracts);
  80. }
  81. if (dataContract != null)
  82. {
  83. if (this.IsGetOnlyCollection && dataContract is SurrogateDataContract)
  84. {
  85. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
  86. DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
  87. }
  88. return dataContract;
  89. }
  90. return base.GetDataContract(id, typeHandle);
  91. }
  92. internal override DataContract GetDataContractSkipValidation(int typeId, RuntimeTypeHandle typeHandle, Type type)
  93. {
  94. DataContract dataContract = null;
  95. if (mode == SerializationMode.SharedType && surrogateSelector != null)
  96. {
  97. dataContract = NetDataContractSerializer.GetDataContractFromSurrogateSelector(surrogateSelector, streamingContext, typeHandle, null /*type*/, ref surrogateDataContracts);
  98. }
  99. if (dataContract != null)
  100. {
  101. if (this.IsGetOnlyCollection && dataContract is SurrogateDataContract)
  102. {
  103. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
  104. DataContract.GetClrTypeFullName(dataContract.UnderlyingType))));
  105. }
  106. return dataContract;
  107. }
  108. return base.GetDataContractSkipValidation(typeId, typeHandle, type);
  109. }
  110. internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, DataContract dataContract)
  111. {
  112. if (mode == SerializationMode.SharedType)
  113. {
  114. NetDataContractSerializer.WriteClrTypeInfo(xmlWriter, dataContract, binder);
  115. return true;
  116. }
  117. return false;
  118. }
  119. internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, Type dataContractType, string clrTypeName, string clrAssemblyName)
  120. {
  121. if (mode == SerializationMode.SharedType)
  122. {
  123. NetDataContractSerializer.WriteClrTypeInfo(xmlWriter, dataContractType, binder, clrTypeName, clrAssemblyName);
  124. return true;
  125. }
  126. return false;
  127. }
  128. internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, Type dataContractType, SerializationInfo serInfo)
  129. {
  130. if (mode == SerializationMode.SharedType)
  131. {
  132. NetDataContractSerializer.WriteClrTypeInfo(xmlWriter, dataContractType, binder, serInfo);
  133. return true;
  134. }
  135. return false;
  136. }
  137. public override void WriteAnyType(XmlWriterDelegator xmlWriter, object value)
  138. {
  139. if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
  140. xmlWriter.WriteAnyType(value);
  141. }
  142. public override void WriteString(XmlWriterDelegator xmlWriter, string value)
  143. {
  144. if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
  145. xmlWriter.WriteString(value);
  146. }
  147. public override void WriteString(XmlWriterDelegator xmlWriter, string value, XmlDictionaryString name, XmlDictionaryString ns)
  148. {
  149. if (value == null)
  150. WriteNull(xmlWriter, typeof(string), true/*isMemberTypeSerializable*/, name, ns);
  151. else
  152. {
  153. xmlWriter.WriteStartElementPrimitive(name, ns);
  154. if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
  155. xmlWriter.WriteString(value);
  156. xmlWriter.WriteEndElementPrimitive();
  157. }
  158. }
  159. public override void WriteBase64(XmlWriterDelegator xmlWriter, byte[] value)
  160. {
  161. if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
  162. xmlWriter.WriteBase64(value);
  163. }
  164. public override void WriteBase64(XmlWriterDelegator xmlWriter, byte[] value, XmlDictionaryString name, XmlDictionaryString ns)
  165. {
  166. if (value == null)
  167. WriteNull(xmlWriter, typeof(byte[]), true/*isMemberTypeSerializable*/, name, ns);
  168. else
  169. {
  170. xmlWriter.WriteStartElementPrimitive(name, ns);
  171. if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
  172. xmlWriter.WriteBase64(value);
  173. xmlWriter.WriteEndElementPrimitive();
  174. }
  175. }
  176. public override void WriteUri(XmlWriterDelegator xmlWriter, Uri value)
  177. {
  178. if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
  179. xmlWriter.WriteUri(value);
  180. }
  181. public override void WriteUri(XmlWriterDelegator xmlWriter, Uri value, XmlDictionaryString name, XmlDictionaryString ns)
  182. {
  183. if (value == null)
  184. WriteNull(xmlWriter, typeof(Uri), true/*isMemberTypeSerializable*/, name, ns);
  185. else
  186. {
  187. xmlWriter.WriteStartElementPrimitive(name, ns);
  188. if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
  189. xmlWriter.WriteUri(value);
  190. xmlWriter.WriteEndElementPrimitive();
  191. }
  192. }
  193. public override void WriteQName(XmlWriterDelegator xmlWriter, XmlQualifiedName value)
  194. {
  195. if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
  196. xmlWriter.WriteQName(value);
  197. }
  198. public override void WriteQName(XmlWriterDelegator xmlWriter, XmlQualifiedName value, XmlDictionaryString name, XmlDictionaryString ns)
  199. {
  200. if (value == null)
  201. WriteNull(xmlWriter, typeof(XmlQualifiedName), true/*isMemberTypeSerializable*/, name, ns);
  202. else
  203. {
  204. if (ns != null && ns.Value != null && ns.Value.Length > 0)
  205. xmlWriter.WriteStartElement(Globals.ElementPrefix, name, ns);
  206. else
  207. xmlWriter.WriteStartElement(name, ns);
  208. if (!OnHandleReference(xmlWriter, value, false /*canContainCyclicReference*/))
  209. xmlWriter.WriteQName(value);
  210. xmlWriter.WriteEndElement();
  211. }
  212. }
  213. public override void InternalSerialize(XmlWriterDelegator xmlWriter, object obj, bool isDeclaredType, bool writeXsiType, int declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
  214. {
  215. if (dataContractSurrogate == null)
  216. {
  217. base.InternalSerialize(xmlWriter, obj, isDeclaredType, writeXsiType, declaredTypeID, declaredTypeHandle);
  218. }
  219. else
  220. {
  221. InternalSerializeWithSurrogate(xmlWriter, obj, isDeclaredType, writeXsiType, declaredTypeID, declaredTypeHandle);
  222. }
  223. }
  224. internal override bool OnHandleReference(XmlWriterDelegator xmlWriter, object obj, bool canContainCyclicReference)
  225. {
  226. if (preserveObjectReferences && !this.IsGetOnlyCollection)
  227. {
  228. bool isNew = true;
  229. int objectId = SerializedObjects.GetId(obj, ref isNew);
  230. if (isNew)
  231. xmlWriter.WriteAttributeInt(Globals.SerPrefix, DictionaryGlobals.IdLocalName, DictionaryGlobals.SerializationNamespace, objectId);
  232. else
  233. {
  234. xmlWriter.WriteAttributeInt(Globals.SerPrefix, DictionaryGlobals.RefLocalName, DictionaryGlobals.SerializationNamespace, objectId);
  235. xmlWriter.WriteAttributeBool(Globals.XsiPrefix, DictionaryGlobals.XsiNilLocalName, DictionaryGlobals.SchemaInstanceNamespace, true);
  236. }
  237. return !isNew;
  238. }
  239. return base.OnHandleReference(xmlWriter, obj, canContainCyclicReference);
  240. }
  241. internal override void OnEndHandleReference(XmlWriterDelegator xmlWriter, object obj, bool canContainCyclicReference)
  242. {
  243. if (preserveObjectReferences && !this.IsGetOnlyCollection)
  244. return;
  245. base.OnEndHandleReference(xmlWriter, obj, canContainCyclicReference);
  246. }
  247. [Fx.Tag.SecurityNote(Critical = "Calls the critical methods of ISurrogateSelector", Safe = "Demands for FullTrust")]
  248. [SecuritySafeCritical]
  249. [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
  250. [MethodImpl(MethodImplOptions.NoInlining)]
  251. bool CheckIfTypeSerializableForSharedTypeMode(Type memberType)
  252. {
  253. Fx.Assert(surrogateSelector != null, "Method should not be called when surrogateSelector is null.");
  254. ISurrogateSelector surrogateSelectorNotUsed;
  255. return (surrogateSelector.GetSurrogate(memberType, streamingContext, out surrogateSelectorNotUsed) != null);
  256. }
  257. internal override void CheckIfTypeSerializable(Type memberType, bool isMemberTypeSerializable)
  258. {
  259. if (mode == SerializationMode.SharedType && surrogateSelector != null &&
  260. CheckIfTypeSerializableForSharedTypeMode(memberType))
  261. {
  262. return;
  263. }
  264. else
  265. {
  266. if (dataContractSurrogate != null)
  267. {
  268. while (memberType.IsArray)
  269. memberType = memberType.GetElementType();
  270. memberType = DataContractSurrogateCaller.GetDataContractType(dataContractSurrogate, memberType);
  271. if (!DataContract.IsTypeSerializable(memberType))
  272. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.TypeNotSerializable, memberType)));
  273. return;
  274. }
  275. }
  276. base.CheckIfTypeSerializable(memberType, isMemberTypeSerializable);
  277. }
  278. internal override Type GetSurrogatedType(Type type)
  279. {
  280. if (dataContractSurrogate == null)
  281. {
  282. return base.GetSurrogatedType(type);
  283. }
  284. else
  285. {
  286. type = DataContract.UnwrapNullableType(type);
  287. Type surrogateType = DataContractSerializer.GetSurrogatedType(dataContractSurrogate, type);
  288. if (this.IsGetOnlyCollection && surrogateType != type)
  289. {
  290. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.GetString(SR.SurrogatesWithGetOnlyCollectionsNotSupportedSerDeser,
  291. DataContract.GetClrTypeFullName(type))));
  292. }
  293. else
  294. {
  295. return surrogateType;
  296. }
  297. }
  298. }
  299. void InternalSerializeWithSurrogate(XmlWriterDelegator xmlWriter, object obj, bool isDeclaredType, bool writeXsiType, int declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
  300. {
  301. RuntimeTypeHandle objTypeHandle = isDeclaredType ? declaredTypeHandle : Type.GetTypeHandle(obj);
  302. object oldObj = obj;
  303. int objOldId = 0;
  304. Type objType = Type.GetTypeFromHandle(objTypeHandle);
  305. Type declaredType = GetSurrogatedType(Type.GetTypeFromHandle(declaredTypeHandle));
  306. if (TD.DCSerializeWithSurrogateStartIsEnabled())
  307. {
  308. TD.DCSerializeWithSurrogateStart(declaredType.FullName);
  309. }
  310. declaredTypeHandle = declaredType.TypeHandle;
  311. obj = DataContractSerializer.SurrogateToDataContractType(dataContractSurrogate, obj, declaredType, ref objType);
  312. objTypeHandle = objType.TypeHandle;
  313. if (oldObj != obj)
  314. objOldId = SerializedObjects.ReassignId(0, oldObj, obj);
  315. if (writeXsiType)
  316. {
  317. declaredType = Globals.TypeOfObject;
  318. SerializeWithXsiType(xmlWriter, obj, objTypeHandle, objType, -1, declaredType.TypeHandle, declaredType);
  319. }
  320. else if (declaredTypeHandle.Equals(objTypeHandle))
  321. {
  322. DataContract contract = GetDataContract(objTypeHandle, objType);
  323. SerializeWithoutXsiType(contract, xmlWriter, obj, declaredTypeHandle);
  324. }
  325. else
  326. {
  327. SerializeWithXsiType(xmlWriter, obj, objTypeHandle, objType, -1, declaredTypeHandle, declaredType);
  328. }
  329. if (oldObj != obj)
  330. SerializedObjects.ReassignId(objOldId, obj, oldObj);
  331. if (TD.DCSerializeWithSurrogateStopIsEnabled())
  332. {
  333. TD.DCSerializeWithSurrogateStop();
  334. }
  335. }
  336. internal override void WriteArraySize(XmlWriterDelegator xmlWriter, int size)
  337. {
  338. if (preserveObjectReferences && size > -1)
  339. xmlWriter.WriteAttributeInt(Globals.SerPrefix, DictionaryGlobals.ArraySizeLocalName, DictionaryGlobals.SerializationNamespace, size);
  340. }
  341. }
  342. }