using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Runtime.Serialization; using System.Xml; using System.Xml.Serialization; namespace DominionBase { [Serializable] public class SerializableDictionary : Dictionary, IXmlSerializable, ISerializable { #region Constants private const string DictionaryNodeName = "Dictionary"; private const string ItemNodeName = "Item"; private const string KeyNodeName = "Key"; private const string ValueNodeName = "Value"; #endregion #region Constructors public SerializableDictionary() { } public SerializableDictionary(IDictionary dictionary) : base(dictionary) { } public SerializableDictionary(IEqualityComparer comparer) : base(comparer) { } public SerializableDictionary(int capacity) : base(capacity) { } public SerializableDictionary(IDictionary dictionary, IEqualityComparer comparer) : base(dictionary, comparer) { } public SerializableDictionary(int capacity, IEqualityComparer comparer) : base(capacity, comparer) { } #endregion #region ISerializable Members protected SerializableDictionary(SerializationInfo info, StreamingContext context) { Contract.Requires(info != null, "info cannot be null"); var itemCount = info.GetInt32("ItemCount"); for (var i = 0; i < itemCount; i++) { var kvp = (KeyValuePair)info.GetValue($"Item{i}", typeof(KeyValuePair)); Add(kvp.Key, kvp.Value); } } void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("ItemCount", Count); var itemIdx = 0; foreach (var kvp in this) { info.AddValue($"Item{itemIdx}", kvp, typeof(KeyValuePair)); itemIdx++; } } #endregion #region IXmlSerializable Members void IXmlSerializable.WriteXml(XmlWriter writer) { //writer.WriteStartElement(DictionaryNodeName); foreach (var kvp in this) { writer.WriteStartElement(ItemNodeName); writer.WriteStartElement(KeyNodeName); KeySerializer.Serialize(writer, kvp.Key); writer.WriteEndElement(); writer.WriteStartElement(ValueNodeName); ValueSerializer.Serialize(writer, kvp.Value); writer.WriteEndElement(); writer.WriteEndElement(); } //writer.WriteEndElement(); } void IXmlSerializable.ReadXml(XmlReader reader) { if (reader.IsEmptyElement) { return; } // Move past container if (!reader.Read()) { throw new XmlException("Error in Deserialization of Dictionary"); } //reader.ReadStartElement(DictionaryNodeName); while (reader.NodeType != XmlNodeType.EndElement) { reader.ReadStartElement(ItemNodeName); reader.ReadStartElement(KeyNodeName); var key = (TKey)KeySerializer.Deserialize(reader); reader.ReadEndElement(); reader.ReadStartElement(ValueNodeName); var value = (TVal)ValueSerializer.Deserialize(reader); reader.ReadEndElement(); reader.ReadEndElement(); Add(key, value); reader.MoveToContent(); } //reader.ReadEndElement(); reader.ReadEndElement(); // Read End Element to close Read of containing node } System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() { return null; } #endregion #region Private Properties protected XmlSerializer ValueSerializer => valueSerializer ?? (valueSerializer = new XmlSerializer(typeof(TVal))); private XmlSerializer KeySerializer => keySerializer ?? (keySerializer = new XmlSerializer(typeof(TKey))); #endregion #region Private Members private XmlSerializer keySerializer; private XmlSerializer valueSerializer; #endregion } }