fork download
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using System.Xml;
  7. using System.Xml.Serialization;
  8.  
  9. namespace DynaXmlSer {
  10.  
  11. public class KnownTypesXmlReader: XmlTextReader {
  12. public KnownTypesXmlReader(Stream ios): base(ios) {}
  13. public Type[] ExtraTypes = null;
  14. }
  15.  
  16. public partial class SerializableSortedDictionary<TKey, TVal>
  17. : SortedDictionary<TKey, TVal>, IXmlSerializable
  18. {
  19. public void SetKnownTypes(Type[] extraTypes) {
  20. this.extraTypes = extraTypes;
  21. valueSerializer = null;
  22. keySerializer = null;
  23. }
  24. void IXmlSerializable.ReadXml(System.Xml.XmlReader reader) {
  25. if (reader.IsEmptyElement)
  26. return;
  27. if (!reader.Read())
  28. throw new XmlException("Error in Deserialization of Dictionary");
  29.  
  30. //HERE IS THE TRICK
  31. if (reader is KnownTypesXmlReader)
  32. SetKnownTypes(((KnownTypesXmlReader)reader).ExtraTypes);
  33.  
  34. //reader.ReadStartElement(DictionaryNodeName);
  35. while (reader.NodeType != XmlNodeType.EndElement)
  36. {
  37. reader.ReadStartElement(ItemNodeName);
  38. reader.ReadStartElement(KeyNodeName);
  39. TKey key = (TKey)KeySerializer.Deserialize(reader);
  40. reader.ReadEndElement();
  41. reader.ReadStartElement(ValueNodeName);
  42. TVal value = (TVal)ValueSerializer.Deserialize(reader);
  43. reader.ReadEndElement();
  44. reader.ReadEndElement();
  45. this.Add(key, value);
  46. reader.MoveToContent();
  47. }
  48. //reader.ReadEndElement();
  49.  
  50. reader.ReadEndElement(); // Read End Element to close Read of containing node
  51. }
  52.  
  53. }
  54.  
  55. public class BasicElement {
  56. private string name;
  57. public string Name {
  58. get { return name; }
  59. set { name = value; } }
  60. }
  61. public class ElementOne: BasicElement {
  62. private string one;
  63. public string One {
  64. get { return one; }
  65. set { one = value; }
  66. }
  67. }
  68. public class ElementTwo: BasicElement {
  69. private string two;
  70. public string Two {
  71. get { return two; }
  72. set { two = value; }
  73. }
  74. }
  75.  
  76. public class Program {
  77. static void Main(string[] args) {
  78. Type[] extraTypes = new Type[] { typeof(ElementOne), typeof(ElementTwo) };
  79. SerializableSortedDictionary<string, BasicElement> dict = new SerializableSortedDictionary<string,BasicElement>();
  80. dict.SetKnownTypes(extraTypes);
  81. dict["foo"] = new ElementOne() { Name = "foo", One = "FOO" };
  82. dict["bar"] = new ElementTwo() { Name = "bar", Two = "BAR" };
  83.  
  84. XmlSerializer ser = new XmlSerializer(typeof(SerializableSortedDictionary<string, BasicElement>));
  85.  
  86. MemoryStream mem = new MemoryStream();
  87. ser.Serialize(mem, dict);
  88. Console.WriteLine(Encoding.UTF8.GetString(mem.ToArray()));
  89. mem.Position = 0;
  90.  
  91. using(XmlReader rd = new KnownTypesXmlReader(mem) { ExtraTypes = extraTypes })
  92. dict = (SerializableSortedDictionary<string, BasicElement>)ser.Deserialize(rd);
  93.  
  94. foreach(KeyValuePair<string, BasicElement> e in dict) {
  95. Console.Write("Key = {0}, Name = {1}", e.Key, e.Value.Name);
  96. if(e.Value is ElementOne) Console.Write(", One = {0}", ((ElementOne)e.Value).One);
  97. else if(e.Value is ElementTwo) Console.Write(", Two = {0}", ((ElementTwo)e.Value).Two);
  98. Console.WriteLine(", Type = {0}", e.Value.GetType().Name);
  99. }
  100. }
  101. }
  102.  
  103. [Serializable]
  104. [XmlRoot("dictionary")]
  105. public partial class SerializableSortedDictionary<TKey, TVal>
  106. : SortedDictionary<TKey, TVal>, IXmlSerializable
  107. {
  108. #region Constants
  109. private const string DictionaryNodeName = "Dictionary";
  110. private const string ItemNodeName = "Item";
  111. private const string KeyNodeName = "Key";
  112. private const string ValueNodeName = "Value";
  113. #endregion
  114.  
  115. #region Constructors
  116. public SerializableSortedDictionary()
  117. {
  118. }
  119.  
  120. public SerializableSortedDictionary(IDictionary<TKey, TVal> dictionary)
  121. : base(dictionary)
  122. {
  123. }
  124.  
  125. public SerializableSortedDictionary(IComparer<TKey> comparer)
  126. : base(comparer)
  127. {
  128. }
  129.  
  130. public SerializableSortedDictionary(IDictionary<TKey, TVal> dictionary, IComparer<TKey> comparer)
  131. : base(dictionary, comparer)
  132. {
  133. }
  134.  
  135. #endregion
  136.  
  137. #region IXmlSerializable Members
  138.  
  139. void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
  140. {
  141. //writer.WriteStartElement(DictionaryNodeName);
  142. foreach (KeyValuePair<TKey, TVal> kvp in this)
  143. {
  144. writer.WriteStartElement(ItemNodeName);
  145. writer.WriteStartElement(KeyNodeName);
  146. KeySerializer.Serialize(writer, kvp.Key);
  147. writer.WriteEndElement();
  148. writer.WriteStartElement(ValueNodeName);
  149. ValueSerializer.Serialize(writer, kvp.Value);
  150. writer.WriteEndElement();
  151. writer.WriteEndElement();
  152. }
  153. //writer.WriteEndElement();
  154. }
  155.  
  156. System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
  157. {
  158. return null;
  159. }
  160.  
  161.  
  162. public Type[] extraTypes = null;
  163.  
  164. #endregion
  165.  
  166. #region Private Properties
  167. protected XmlSerializer ValueSerializer
  168. {
  169. get
  170. {
  171. if (valueSerializer == null)
  172. {
  173. if (extraTypes == null)
  174. valueSerializer = new XmlSerializer(typeof(TVal));
  175. else
  176. valueSerializer = new XmlSerializer(typeof(TVal), extraTypes);
  177. }
  178. return valueSerializer;
  179. }
  180. }
  181.  
  182. private XmlSerializer KeySerializer
  183. {
  184. get
  185. {
  186. if (keySerializer == null)
  187. {
  188. if (extraTypes == null)
  189. keySerializer = new XmlSerializer(typeof(TKey));
  190. else
  191. keySerializer = new XmlSerializer(typeof(TKey), extraTypes);
  192. }
  193. return keySerializer;
  194. }
  195. }
  196. #endregion
  197. #region Private Members
  198. [NonSerialized]
  199. private XmlSerializer keySerializer = null;
  200. [NonSerialized]
  201. private XmlSerializer valueSerializer = null;
  202. #endregion
  203. }
  204.  
  205. }
  206.  
Success #stdin #stdout 0.25s 41080KB
stdin
Standard input is empty
stdout
<?xml version="1.0" encoding="utf-8"?>
<dictionary>
  <Item>
    <Key>
      <string>bar</string>
    </Key>
    <Value>
      <BasicElement xmlns:xsi="http://w...content-available-to-author-only...3.org/2001/XMLSchema-instance" xmlns:xsd="http://w...content-available-to-author-only...3.org/2001/XMLSchema" xsi:type="ElementTwo">
        <Name>bar</Name>
        <Two>BAR</Two>
      </BasicElement>
    </Value>
  </Item>
  <Item>
    <Key>
      <string>foo</string>
    </Key>
    <Value>
      <BasicElement xmlns:xsi="http://w...content-available-to-author-only...3.org/2001/XMLSchema-instance" xmlns:xsd="http://w...content-available-to-author-only...3.org/2001/XMLSchema" xsi:type="ElementOne">
        <Name>foo</Name>
        <One>FOO</One>
      </BasicElement>
    </Value>
  </Item>
</dictionary>
Key = bar, Name = bar, Two = BAR, Type = ElementTwo
Key = foo, Name = foo, One = FOO, Type = ElementOne