ExtensionDataReader.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.Runtime.Serialization
  5. {
  6. using System;
  7. using System.Text;
  8. using System.IO;
  9. using System.Xml;
  10. using System.Diagnostics;
  11. using System.Collections;
  12. using System.Collections.Generic;
  13. using System.Globalization;
  14. using System.Security;
  15. // NOTE: XmlReader methods that are not needed have been left un-implemented
  16. class ExtensionDataReader : XmlReader
  17. {
  18. enum ExtensionDataNodeType
  19. {
  20. None,
  21. Element,
  22. EndElement,
  23. Text,
  24. Xml,
  25. ReferencedElement,
  26. NullElement,
  27. }
  28. Hashtable cache = new Hashtable();
  29. ElementData[] elements;
  30. ElementData element;
  31. ElementData nextElement;
  32. ReadState readState = ReadState.Initial;
  33. ExtensionDataNodeType internalNodeType;
  34. XmlNodeType nodeType;
  35. int depth;
  36. string localName;
  37. string ns;
  38. string prefix;
  39. string value;
  40. int attributeCount;
  41. int attributeIndex;
  42. XmlNodeReader xmlNodeReader;
  43. Queue<IDataNode> deserializedDataNodes;
  44. XmlObjectSerializerReadContext context;
  45. [Fx.Tag.SecurityNote(Critical = "Holds static mappings from namespaces to prefixes."
  46. + " Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
  47. [SecurityCritical]
  48. static Dictionary<string, string> nsToPrefixTable;
  49. [Fx.Tag.SecurityNote(Critical = "Holds static mappings from prefixes to namespaces."
  50. + " Static fields are marked SecurityCritical or readonly to prevent data from being modified or leaked to other components in appdomain.")]
  51. [SecurityCritical]
  52. static Dictionary<string, string> prefixToNsTable;
  53. [Fx.Tag.SecurityNote(Critical = "Initializes information in critical static cache.",
  54. Safe = "Cache is initialized with well-known namespace, prefix mappings.")]
  55. [SecuritySafeCritical]
  56. static ExtensionDataReader()
  57. {
  58. nsToPrefixTable = new Dictionary<string, string>();
  59. prefixToNsTable = new Dictionary<string, string>();
  60. AddPrefix(Globals.XsiPrefix, Globals.SchemaInstanceNamespace);
  61. AddPrefix(Globals.SerPrefix, Globals.SerializationNamespace);
  62. AddPrefix(String.Empty, String.Empty);
  63. }
  64. internal ExtensionDataReader(XmlObjectSerializerReadContext context)
  65. {
  66. this.attributeIndex = -1;
  67. this.context = context;
  68. }
  69. internal void SetDeserializedValue(object obj)
  70. {
  71. IDataNode deserializedDataNode = (deserializedDataNodes == null || deserializedDataNodes.Count == 0) ? null : deserializedDataNodes.Dequeue();
  72. if (deserializedDataNode != null && !(obj is IDataNode))
  73. {
  74. deserializedDataNode.Value = obj;
  75. deserializedDataNode.IsFinalValue = true;
  76. }
  77. }
  78. internal IDataNode GetCurrentNode()
  79. {
  80. IDataNode retVal = element.dataNode;
  81. Skip();
  82. return retVal;
  83. }
  84. internal void SetDataNode(IDataNode dataNode, string name, string ns)
  85. {
  86. SetNextElement(dataNode, name, ns, null);
  87. this.element = nextElement;
  88. this.nextElement = null;
  89. SetElement();
  90. }
  91. internal void Reset()
  92. {
  93. this.localName = null;
  94. this.ns = null;
  95. this.prefix = null;
  96. this.value = null;
  97. this.attributeCount = 0;
  98. this.attributeIndex = -1;
  99. this.depth = 0;
  100. this.element = null;
  101. this.nextElement = null;
  102. this.elements = null;
  103. this.deserializedDataNodes = null;
  104. }
  105. bool IsXmlDataNode { get { return (internalNodeType == ExtensionDataNodeType.Xml); } }
  106. public override XmlNodeType NodeType { get { return IsXmlDataNode ? xmlNodeReader.NodeType : nodeType; } }
  107. public override string LocalName { get { return IsXmlDataNode ? xmlNodeReader.LocalName : localName; } }
  108. public override string NamespaceURI { get { return IsXmlDataNode ? xmlNodeReader.NamespaceURI : ns; } }
  109. public override string Prefix { get { return IsXmlDataNode ? xmlNodeReader.Prefix : prefix; } }
  110. public override string Value { get { return IsXmlDataNode ? xmlNodeReader.Value : value; } }
  111. public override int Depth { get { return IsXmlDataNode ? xmlNodeReader.Depth : depth; } }
  112. public override int AttributeCount { get { return IsXmlDataNode ? xmlNodeReader.AttributeCount : attributeCount; } }
  113. public override bool EOF { get { return IsXmlDataNode ? xmlNodeReader.EOF : (readState == ReadState.EndOfFile); } }
  114. public override ReadState ReadState { get { return IsXmlDataNode ? xmlNodeReader.ReadState : readState; } }
  115. public override bool IsEmptyElement { get { return IsXmlDataNode ? xmlNodeReader.IsEmptyElement : false; } }
  116. public override bool IsDefault { get { return IsXmlDataNode ? xmlNodeReader.IsDefault : base.IsDefault; } }
  117. public override char QuoteChar { get { return IsXmlDataNode ? xmlNodeReader.QuoteChar : base.QuoteChar; } }
  118. public override XmlSpace XmlSpace { get { return IsXmlDataNode ? xmlNodeReader.XmlSpace : base.XmlSpace; } }
  119. public override string XmlLang { get { return IsXmlDataNode ? xmlNodeReader.XmlLang : base.XmlLang; } }
  120. public override string this[int i] { get { return IsXmlDataNode ? xmlNodeReader[i] : GetAttribute(i); } }
  121. public override string this[string name] { get { return IsXmlDataNode ? xmlNodeReader[name] : GetAttribute(name); } }
  122. public override string this[string name, string namespaceURI] { get { return IsXmlDataNode ? xmlNodeReader[name, namespaceURI] : GetAttribute(name, namespaceURI); } }
  123. public override bool MoveToFirstAttribute()
  124. {
  125. if (IsXmlDataNode)
  126. return xmlNodeReader.MoveToFirstAttribute();
  127. if (attributeCount == 0)
  128. return false;
  129. MoveToAttribute(0);
  130. return true;
  131. }
  132. public override bool MoveToNextAttribute()
  133. {
  134. if (IsXmlDataNode)
  135. return xmlNodeReader.MoveToNextAttribute();
  136. if (attributeIndex + 1 >= attributeCount)
  137. return false;
  138. MoveToAttribute(attributeIndex + 1);
  139. return true;
  140. }
  141. public override void MoveToAttribute(int index)
  142. {
  143. if (IsXmlDataNode)
  144. xmlNodeReader.MoveToAttribute(index);
  145. else
  146. {
  147. if (index < 0 || index >= attributeCount)
  148. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.InvalidXmlDeserializingExtensionData)));
  149. this.nodeType = XmlNodeType.Attribute;
  150. AttributeData attribute = element.attributes[index];
  151. this.localName = attribute.localName;
  152. this.ns = attribute.ns;
  153. this.prefix = attribute.prefix;
  154. this.value = attribute.value;
  155. this.attributeIndex = index;
  156. }
  157. }
  158. public override string GetAttribute(string name, string namespaceURI)
  159. {
  160. if (IsXmlDataNode)
  161. return xmlNodeReader.GetAttribute(name, namespaceURI);
  162. for (int i = 0; i < element.attributeCount; i++)
  163. {
  164. AttributeData attribute = element.attributes[i];
  165. if (attribute.localName == name && attribute.ns == namespaceURI)
  166. return attribute.value;
  167. }
  168. return null;
  169. }
  170. public override bool MoveToAttribute(string name, string namespaceURI)
  171. {
  172. if (IsXmlDataNode)
  173. return xmlNodeReader.MoveToAttribute(name, ns);
  174. for (int i = 0; i < element.attributeCount; i++)
  175. {
  176. AttributeData attribute = element.attributes[i];
  177. if (attribute.localName == name && attribute.ns == namespaceURI)
  178. {
  179. MoveToAttribute(i);
  180. return true;
  181. }
  182. }
  183. return false;
  184. }
  185. public override bool MoveToElement()
  186. {
  187. if (IsXmlDataNode)
  188. return xmlNodeReader.MoveToElement();
  189. if (this.nodeType != XmlNodeType.Attribute)
  190. return false;
  191. SetElement();
  192. return true;
  193. }
  194. void SetElement()
  195. {
  196. this.nodeType = XmlNodeType.Element;
  197. this.localName = element.localName;
  198. this.ns = element.ns;
  199. this.prefix = element.prefix;
  200. this.value = String.Empty;
  201. this.attributeCount = element.attributeCount;
  202. this.attributeIndex = -1;
  203. }
  204. [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up namespace given a prefix.",
  205. Safe = "Read only access.")]
  206. [SecuritySafeCritical]
  207. public override string LookupNamespace(string prefix)
  208. {
  209. if (IsXmlDataNode)
  210. return xmlNodeReader.LookupNamespace(prefix);
  211. string ns;
  212. if (!prefixToNsTable.TryGetValue(prefix, out ns))
  213. return null;
  214. return ns;
  215. }
  216. public override void Skip()
  217. {
  218. if (IsXmlDataNode)
  219. xmlNodeReader.Skip();
  220. else
  221. {
  222. if (ReadState != ReadState.Interactive)
  223. return;
  224. MoveToElement();
  225. if (IsElementNode(this.internalNodeType))
  226. {
  227. int depth = 1;
  228. while (depth != 0)
  229. {
  230. if (!Read())
  231. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.InvalidXmlDeserializingExtensionData)));
  232. if (IsElementNode(this.internalNodeType))
  233. depth++;
  234. else if (this.internalNodeType == ExtensionDataNodeType.EndElement)
  235. {
  236. ReadEndElement();
  237. depth--;
  238. }
  239. }
  240. }
  241. else
  242. Read();
  243. }
  244. }
  245. bool IsElementNode(ExtensionDataNodeType nodeType)
  246. {
  247. return (nodeType == ExtensionDataNodeType.Element ||
  248. nodeType == ExtensionDataNodeType.ReferencedElement ||
  249. nodeType == ExtensionDataNodeType.NullElement);
  250. }
  251. public override void Close()
  252. {
  253. if (IsXmlDataNode)
  254. xmlNodeReader.Close();
  255. else
  256. {
  257. Reset();
  258. this.readState = ReadState.Closed;
  259. }
  260. }
  261. public override bool Read()
  262. {
  263. if (nodeType == XmlNodeType.Attribute && MoveToNextAttribute())
  264. return true;
  265. MoveNext(element.dataNode);
  266. switch (internalNodeType)
  267. {
  268. case ExtensionDataNodeType.Element:
  269. case ExtensionDataNodeType.ReferencedElement:
  270. case ExtensionDataNodeType.NullElement:
  271. PushElement();
  272. SetElement();
  273. break;
  274. case ExtensionDataNodeType.Text:
  275. this.nodeType = XmlNodeType.Text;
  276. this.prefix = String.Empty;
  277. this.ns = String.Empty;
  278. this.localName = String.Empty;
  279. this.attributeCount = 0;
  280. this.attributeIndex = -1;
  281. break;
  282. case ExtensionDataNodeType.EndElement:
  283. this.nodeType = XmlNodeType.EndElement;
  284. this.prefix = String.Empty;
  285. this.ns = String.Empty;
  286. this.localName = String.Empty;
  287. this.value = String.Empty;
  288. this.attributeCount = 0;
  289. this.attributeIndex = -1;
  290. PopElement();
  291. break;
  292. case ExtensionDataNodeType.None:
  293. if (depth != 0)
  294. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.InvalidXmlDeserializingExtensionData)));
  295. this.nodeType = XmlNodeType.None;
  296. this.prefix = String.Empty;
  297. this.ns = String.Empty;
  298. this.localName = String.Empty;
  299. this.value = String.Empty;
  300. this.attributeCount = 0;
  301. readState = ReadState.EndOfFile;
  302. return false;
  303. case ExtensionDataNodeType.Xml:
  304. // do nothing
  305. break;
  306. default:
  307. Fx.Assert("ExtensionDataReader in invalid state");
  308. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.InvalidStateInExtensionDataReader)));
  309. }
  310. readState = ReadState.Interactive;
  311. return true;
  312. }
  313. public override string Name
  314. {
  315. get
  316. {
  317. if (IsXmlDataNode)
  318. {
  319. return xmlNodeReader.Name;
  320. }
  321. Fx.Assert("ExtensionDataReader Name property should only be called for IXmlSerializable");
  322. return string.Empty;
  323. }
  324. }
  325. public override bool HasValue
  326. {
  327. get
  328. {
  329. if (IsXmlDataNode)
  330. {
  331. return xmlNodeReader.HasValue;
  332. }
  333. Fx.Assert("ExtensionDataReader HasValue property should only be called for IXmlSerializable");
  334. return false;
  335. }
  336. }
  337. public override string BaseURI
  338. {
  339. get
  340. {
  341. if (IsXmlDataNode)
  342. {
  343. return xmlNodeReader.BaseURI;
  344. }
  345. Fx.Assert("ExtensionDataReader BaseURI property should only be called for IXmlSerializable");
  346. return string.Empty;
  347. }
  348. }
  349. public override XmlNameTable NameTable
  350. {
  351. get
  352. {
  353. if (IsXmlDataNode)
  354. {
  355. return xmlNodeReader.NameTable;
  356. }
  357. Fx.Assert("ExtensionDataReader NameTable property should only be called for IXmlSerializable");
  358. return null;
  359. }
  360. }
  361. public override string GetAttribute(string name)
  362. {
  363. if (IsXmlDataNode)
  364. {
  365. return xmlNodeReader.GetAttribute(name);
  366. }
  367. Fx.Assert("ExtensionDataReader GetAttribute method should only be called for IXmlSerializable");
  368. return null;
  369. }
  370. public override string GetAttribute(int i)
  371. {
  372. if (IsXmlDataNode)
  373. {
  374. return xmlNodeReader.GetAttribute(i);
  375. }
  376. Fx.Assert("ExtensionDataReader GetAttribute method should only be called for IXmlSerializable");
  377. return null;
  378. }
  379. public override bool MoveToAttribute(string name)
  380. {
  381. if (IsXmlDataNode)
  382. {
  383. return xmlNodeReader.MoveToAttribute(name);
  384. }
  385. Fx.Assert("ExtensionDataReader MoveToAttribute method should only be called for IXmlSerializable");
  386. return false;
  387. }
  388. public override void ResolveEntity()
  389. {
  390. if (IsXmlDataNode)
  391. {
  392. xmlNodeReader.ResolveEntity();
  393. }
  394. else
  395. {
  396. Fx.Assert("ExtensionDataReader ResolveEntity method should only be called for IXmlSerializable");
  397. }
  398. }
  399. public override bool ReadAttributeValue()
  400. {
  401. if (IsXmlDataNode)
  402. {
  403. return xmlNodeReader.ReadAttributeValue();
  404. }
  405. Fx.Assert("ExtensionDataReader ReadAttributeValue method should only be called for IXmlSerializable");
  406. return false;
  407. }
  408. void MoveNext(IDataNode dataNode)
  409. {
  410. switch (this.internalNodeType)
  411. {
  412. case ExtensionDataNodeType.Text:
  413. case ExtensionDataNodeType.ReferencedElement:
  414. case ExtensionDataNodeType.NullElement:
  415. this.internalNodeType = ExtensionDataNodeType.EndElement;
  416. return;
  417. default:
  418. Type dataNodeType = dataNode.DataType;
  419. if (dataNodeType == Globals.TypeOfClassDataNode)
  420. MoveNextInClass((ClassDataNode)dataNode);
  421. else if (dataNodeType == Globals.TypeOfCollectionDataNode)
  422. MoveNextInCollection((CollectionDataNode)dataNode);
  423. else if (dataNodeType == Globals.TypeOfISerializableDataNode)
  424. MoveNextInISerializable((ISerializableDataNode)dataNode);
  425. else if (dataNodeType == Globals.TypeOfXmlDataNode)
  426. MoveNextInXml((XmlDataNode)dataNode);
  427. else if (dataNode.Value != null)
  428. MoveToDeserializedObject(dataNode);
  429. else
  430. {
  431. Fx.Assert("Encountered invalid data node when deserializing unknown data");
  432. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.InvalidStateInExtensionDataReader)));
  433. }
  434. break;
  435. }
  436. }
  437. void SetNextElement(IDataNode node, string name, string ns, string prefix)
  438. {
  439. this.internalNodeType = ExtensionDataNodeType.Element;
  440. nextElement = GetNextElement();
  441. nextElement.localName = name;
  442. nextElement.ns = ns;
  443. nextElement.prefix = prefix;
  444. if (node == null)
  445. {
  446. nextElement.attributeCount = 0;
  447. nextElement.AddAttribute(Globals.XsiPrefix, Globals.SchemaInstanceNamespace, Globals.XsiNilLocalName, Globals.True);
  448. this.internalNodeType = ExtensionDataNodeType.NullElement;
  449. }
  450. else if (!CheckIfNodeHandled(node))
  451. {
  452. AddDeserializedDataNode(node);
  453. node.GetData(nextElement);
  454. if (node is XmlDataNode)
  455. MoveNextInXml((XmlDataNode)node);
  456. }
  457. }
  458. void AddDeserializedDataNode(IDataNode node)
  459. {
  460. if (node.Id != Globals.NewObjectId && (node.Value == null || !node.IsFinalValue))
  461. {
  462. if (deserializedDataNodes == null)
  463. deserializedDataNodes = new Queue<IDataNode>();
  464. deserializedDataNodes.Enqueue(node);
  465. }
  466. }
  467. bool CheckIfNodeHandled(IDataNode node)
  468. {
  469. bool handled = false;
  470. if (node.Id != Globals.NewObjectId)
  471. {
  472. handled = (cache[node] != null);
  473. if (handled)
  474. {
  475. if (nextElement == null)
  476. nextElement = GetNextElement();
  477. nextElement.attributeCount = 0;
  478. nextElement.AddAttribute(Globals.SerPrefix, Globals.SerializationNamespace, Globals.RefLocalName, node.Id.ToString(NumberFormatInfo.InvariantInfo));
  479. nextElement.AddAttribute(Globals.XsiPrefix, Globals.SchemaInstanceNamespace, Globals.XsiNilLocalName, Globals.True);
  480. this.internalNodeType = ExtensionDataNodeType.ReferencedElement;
  481. }
  482. else
  483. {
  484. cache.Add(node, node);
  485. }
  486. }
  487. return handled;
  488. }
  489. void MoveNextInClass(ClassDataNode dataNode)
  490. {
  491. if (dataNode.Members != null && element.childElementIndex < dataNode.Members.Count)
  492. {
  493. if (element.childElementIndex == 0)
  494. this.context.IncrementItemCount(-dataNode.Members.Count);
  495. ExtensionDataMember member = dataNode.Members[element.childElementIndex++];
  496. SetNextElement(member.Value, member.Name, member.Namespace, GetPrefix(member.Namespace));
  497. }
  498. else
  499. {
  500. this.internalNodeType = ExtensionDataNodeType.EndElement;
  501. element.childElementIndex = 0;
  502. }
  503. }
  504. void MoveNextInCollection(CollectionDataNode dataNode)
  505. {
  506. if (dataNode.Items != null && element.childElementIndex < dataNode.Items.Count)
  507. {
  508. if (element.childElementIndex == 0)
  509. this.context.IncrementItemCount(-dataNode.Items.Count);
  510. IDataNode item = dataNode.Items[element.childElementIndex++];
  511. SetNextElement(item, dataNode.ItemName, dataNode.ItemNamespace, GetPrefix(dataNode.ItemNamespace));
  512. }
  513. else
  514. {
  515. this.internalNodeType = ExtensionDataNodeType.EndElement;
  516. element.childElementIndex = 0;
  517. }
  518. }
  519. void MoveNextInISerializable(ISerializableDataNode dataNode)
  520. {
  521. if (dataNode.Members != null && element.childElementIndex < dataNode.Members.Count)
  522. {
  523. if (element.childElementIndex == 0)
  524. this.context.IncrementItemCount(-dataNode.Members.Count);
  525. ISerializableDataMember member = dataNode.Members[element.childElementIndex++];
  526. SetNextElement(member.Value, member.Name, String.Empty, String.Empty);
  527. }
  528. else
  529. {
  530. this.internalNodeType = ExtensionDataNodeType.EndElement;
  531. element.childElementIndex = 0;
  532. }
  533. }
  534. void MoveNextInXml(XmlDataNode dataNode)
  535. {
  536. if (IsXmlDataNode)
  537. {
  538. xmlNodeReader.Read();
  539. if (xmlNodeReader.Depth == 0)
  540. {
  541. this.internalNodeType = ExtensionDataNodeType.EndElement;
  542. xmlNodeReader = null;
  543. }
  544. }
  545. else
  546. {
  547. internalNodeType = ExtensionDataNodeType.Xml;
  548. if (element == null)
  549. element = nextElement;
  550. else
  551. PushElement();
  552. XmlNode wrapperElement = XmlObjectSerializerReadContext.CreateWrapperXmlElement(dataNode.OwnerDocument,
  553. dataNode.XmlAttributes, dataNode.XmlChildNodes, element.prefix, element.localName, element.ns);
  554. for (int i = 0; i < element.attributeCount; i++)
  555. {
  556. AttributeData a = element.attributes[i];
  557. XmlAttribute xmlAttr = dataNode.OwnerDocument.CreateAttribute(a.prefix, a.localName, a.ns);
  558. xmlAttr.Value = a.value;
  559. wrapperElement.Attributes.Append(xmlAttr);
  560. }
  561. xmlNodeReader = new XmlNodeReader(wrapperElement);
  562. xmlNodeReader.Read();
  563. }
  564. }
  565. void MoveToDeserializedObject(IDataNode dataNode)
  566. {
  567. Type type = dataNode.DataType;
  568. bool isTypedNode = true;
  569. if (type == Globals.TypeOfObject)
  570. {
  571. type = dataNode.Value.GetType();
  572. if (type == Globals.TypeOfObject)
  573. {
  574. this.internalNodeType = ExtensionDataNodeType.EndElement;
  575. return;
  576. }
  577. isTypedNode = false;
  578. }
  579. if (!MoveToText(type, dataNode, isTypedNode))
  580. {
  581. if (dataNode.IsFinalValue)
  582. {
  583. this.internalNodeType = ExtensionDataNodeType.EndElement;
  584. }
  585. else
  586. {
  587. throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.InvalidDataNode, DataContract.GetClrTypeFullName(type))));
  588. }
  589. }
  590. }
  591. bool MoveToText(Type type, IDataNode dataNode, bool isTypedNode)
  592. {
  593. bool handled = true;
  594. switch (Type.GetTypeCode(type))
  595. {
  596. case TypeCode.Boolean:
  597. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<bool>)dataNode).GetValue() : (bool)dataNode.Value);
  598. break;
  599. case TypeCode.Char:
  600. this.value = XmlConvert.ToString((int)(isTypedNode ? ((DataNode<char>)dataNode).GetValue() : (char)dataNode.Value));
  601. break;
  602. case TypeCode.Byte:
  603. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<byte>)dataNode).GetValue() : (byte)dataNode.Value);
  604. break;
  605. case TypeCode.Int16:
  606. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<short>)dataNode).GetValue() : (short)dataNode.Value);
  607. break;
  608. case TypeCode.Int32:
  609. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<int>)dataNode).GetValue() : (int)dataNode.Value);
  610. break;
  611. case TypeCode.Int64:
  612. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<long>)dataNode).GetValue() : (long)dataNode.Value);
  613. break;
  614. case TypeCode.Single:
  615. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<float>)dataNode).GetValue() : (float)dataNode.Value);
  616. break;
  617. case TypeCode.Double:
  618. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<double>)dataNode).GetValue() : (double)dataNode.Value);
  619. break;
  620. case TypeCode.Decimal:
  621. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<decimal>)dataNode).GetValue() : (decimal)dataNode.Value);
  622. break;
  623. case TypeCode.DateTime:
  624. DateTime dateTime = isTypedNode ? ((DataNode<DateTime>)dataNode).GetValue() : (DateTime)dataNode.Value;
  625. this.value = dateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffffffK", DateTimeFormatInfo.InvariantInfo);
  626. break;
  627. case TypeCode.String:
  628. this.value = isTypedNode ? ((DataNode<string>)dataNode).GetValue() : (string)dataNode.Value;
  629. break;
  630. case TypeCode.SByte:
  631. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<sbyte>)dataNode).GetValue() : (sbyte)dataNode.Value);
  632. break;
  633. case TypeCode.UInt16:
  634. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<ushort>)dataNode).GetValue() : (ushort)dataNode.Value);
  635. break;
  636. case TypeCode.UInt32:
  637. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<uint>)dataNode).GetValue() : (uint)dataNode.Value);
  638. break;
  639. case TypeCode.UInt64:
  640. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<ulong>)dataNode).GetValue() : (ulong)dataNode.Value);
  641. break;
  642. case TypeCode.Object:
  643. default:
  644. if (type == Globals.TypeOfByteArray)
  645. {
  646. byte[] bytes = isTypedNode ? ((DataNode<byte[]>)dataNode).GetValue() : (byte[])dataNode.Value;
  647. this.value = (bytes == null) ? String.Empty : Convert.ToBase64String(bytes);
  648. }
  649. else if (type == Globals.TypeOfTimeSpan)
  650. this.value = XmlConvert.ToString(isTypedNode ? ((DataNode<TimeSpan>)dataNode).GetValue() : (TimeSpan)dataNode.Value);
  651. else if (type == Globals.TypeOfGuid)
  652. {
  653. Guid guid = isTypedNode ? ((DataNode<Guid>)dataNode).GetValue() : (Guid)dataNode.Value;
  654. this.value = guid.ToString();
  655. }
  656. else if (type == Globals.TypeOfUri)
  657. {
  658. Uri uri = isTypedNode ? ((DataNode<Uri>)dataNode).GetValue() : (Uri)dataNode.Value;
  659. this.value = uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
  660. }
  661. else
  662. handled = false;
  663. break;
  664. }
  665. if (handled)
  666. this.internalNodeType = ExtensionDataNodeType.Text;
  667. return handled;
  668. }
  669. void PushElement()
  670. {
  671. GrowElementsIfNeeded();
  672. elements[depth++] = this.element;
  673. if (nextElement == null)
  674. element = GetNextElement();
  675. else
  676. {
  677. element = nextElement;
  678. nextElement = null;
  679. }
  680. }
  681. void PopElement()
  682. {
  683. this.prefix = element.prefix;
  684. this.localName = element.localName;
  685. this.ns = element.ns;
  686. if (depth == 0)
  687. return;
  688. this.depth--;
  689. if (elements != null)
  690. {
  691. this.element = elements[depth];
  692. }
  693. }
  694. void GrowElementsIfNeeded()
  695. {
  696. if (elements == null)
  697. elements = new ElementData[8];
  698. else if (elements.Length == depth)
  699. {
  700. ElementData[] newElements = new ElementData[elements.Length * 2];
  701. Array.Copy(elements, 0, newElements, 0, elements.Length);
  702. elements = newElements;
  703. }
  704. }
  705. ElementData GetNextElement()
  706. {
  707. int nextDepth = depth + 1;
  708. return (elements == null || elements.Length <= nextDepth || elements[nextDepth] == null)
  709. ? new ElementData() : elements[nextDepth];
  710. }
  711. [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up prefix given a namespace .",
  712. Safe = "Read only access.")]
  713. [SecuritySafeCritical]
  714. internal static string GetPrefix(string ns)
  715. {
  716. string prefix;
  717. ns = ns ?? String.Empty;
  718. if (!nsToPrefixTable.TryGetValue(ns, out prefix))
  719. {
  720. lock (nsToPrefixTable)
  721. {
  722. if (!nsToPrefixTable.TryGetValue(ns, out prefix))
  723. {
  724. prefix = (ns == null || ns.Length == 0) ? String.Empty : "p" + nsToPrefixTable.Count;
  725. AddPrefix(prefix, ns);
  726. }
  727. }
  728. }
  729. return prefix;
  730. }
  731. [Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical static cache to look up prefix given a namespace .",
  732. Safe = "Read only access.")]
  733. [SecuritySafeCritical]
  734. static void AddPrefix(string prefix, string ns)
  735. {
  736. nsToPrefixTable.Add(ns, prefix);
  737. prefixToNsTable.Add(prefix, ns);
  738. }
  739. }
  740. #if USE_REFEMIT
  741. public class AttributeData
  742. #else
  743. internal class AttributeData
  744. #endif
  745. {
  746. public string prefix;
  747. public string ns;
  748. public string localName;
  749. public string value;
  750. }
  751. #if USE_REFEMIT
  752. public class ElementData
  753. #else
  754. internal class ElementData
  755. #endif
  756. {
  757. public string localName;
  758. public string ns;
  759. public string prefix;
  760. public int attributeCount;
  761. public AttributeData[] attributes;
  762. public IDataNode dataNode;
  763. public int childElementIndex;
  764. public void AddAttribute(string prefix, string ns, string name, string value)
  765. {
  766. GrowAttributesIfNeeded();
  767. AttributeData attribute = attributes[attributeCount];
  768. if (attribute == null)
  769. attributes[attributeCount] = attribute = new AttributeData();
  770. attribute.prefix = prefix;
  771. attribute.ns = ns;
  772. attribute.localName = name;
  773. attribute.value = value;
  774. attributeCount++;
  775. }
  776. void GrowAttributesIfNeeded()
  777. {
  778. if (attributes == null)
  779. attributes = new AttributeData[4];
  780. else if (attributes.Length == attributeCount)
  781. {
  782. AttributeData[] newAttributes = new AttributeData[attributes.Length * 2];
  783. Array.Copy(attributes, 0, newAttributes, 0, attributes.Length);
  784. attributes = newAttributes;
  785. }
  786. }
  787. }
  788. }