< 1 min read

The Dictionary class included in C# isn’t serializable, so you can use the following Serializable Dictionary whenever you need to serialize your objects

[Serializable]
public class SerializableDictionary : Dictionary, IXmlSerializable, ISerializable
{
  #region Private Properties

  protected XmlSerializer ValueSerializer
  {
    get { return _valueSerializer ?? (_valueSerializer = new XmlSerializer(typeof(TVal))); }
  }

  private XmlSerializer KeySerializer
  { 
    get { return _keySerializer ?? (_keySerializer = new XmlSerializer(typeof(TKey)));}
  }

  #endregion


  #region Private Members

  private XmlSerializer _keySerializer;

  private XmlSerializer _valueSerializer;

  #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)
  {
    int itemCount = info.GetInt32("itemsCount");

    for (int i = 0; i < itemCount; i++)
    {
      KeyValuePair kvp = (KeyValuePair)info.GetValue(String.Format(CultureInfo.InvariantCulture, "Item{0}", i), typeof(KeyValuePair));
      Add(kvp.Key, kvp.Value);
    }
  }

  void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
  {
    info.AddValue("itemsCount", Count);
    int itemIdx = 0; foreach (KeyValuePair kvp in this)
    {
      info.AddValue(String.Format(CultureInfo.InvariantCulture, "Item{0}", itemIdx), kvp, typeof(KeyValuePair));
      itemIdx++;
    }
  }

  #endregion


  #region IXmlSerializable Members

  void IXmlSerializable.WriteXml(XmlWriter writer)
  {
    foreach (KeyValuePair kvp in this)
    {
      writer.WriteStartElement("item");
      writer.WriteStartElement("key");
      KeySerializer.Serialize(writer, kvp.Key);
      writer.WriteEndElement();
      writer.WriteStartElement("value");
      ValueSerializer.Serialize(writer, kvp.Value);
      writer.WriteEndElement();
      writer.WriteEndElement();
    }
  }

  void IXmlSerializable.ReadXml(XmlReader reader)
  {
    if (reader.IsEmptyElement)
    {
      return;
    }

    // Move past container
    if (reader.NodeType == XmlNodeType.Element && !reader.Read())
      throw new XmlException("Error in De serialization of SerializableDictionary");

    while (reader.NodeType != XmlNodeType.EndElement)
    {
      reader.ReadStartElement("item");
      reader.ReadStartElement("key");
      TKey key = (TKey)KeySerializer.Deserialize(reader);
      reader.ReadEndElement();
      reader.ReadStartElement("value");
      TVal value = (TVal)ValueSerializer.Deserialize(reader);
      reader.ReadEndElement();
      reader.ReadEndElement();
      Add(key, value);
      reader.MoveToContent();
    }

    // Move past container
    if (reader.NodeType == XmlNodeType.EndElement)
    {
      reader.ReadEndElement();
    }
    else
    {
      throw new XmlException("Error in Deserialization of SerializableDictionary");
    }
  }

  System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
  {
    return null;
  }

  #endregion
}

Was this post helpful?