Friday, December 31, 2010

Binary and Xml Serializable Dictionary

You can also see my codeproject article Both Xml and Binary Serializable Dictionary
I had a project where I needed to use binary serialization for deep copy and also needed Xml serialization for saving these into database.
Dictionary class is not by default xml serializable. For making it serializable we  need to implement a derived class implement interface IXmlSerializable. Also to get all functionality of Dictionary I have implemented that class from Dictionary class. The key type of Dictionary is string as I needed so I make it string for simplicity.
[XmlRoot("Dictionary")]
public class SerializableDictionary<VT>:Dictionary<string,VT>,IXmlSerializable


IXmlSerializable class contains following method that we needed to implement in our class


public interface IXmlSerializable
{
XmlSchema GetSchema();
void ReadXml(XmlReader reader);
void WriteXml(XmlWriter writer);
}   


But we also have to make our dictionary binary serializable. For serialization we need to set serializable attribute over our derived class. However when we try to deserialize our derived class in raise error saying there is no appropriate contractor to deserialize our class though default constructor exist. Dictionary<> class implements its own custom serialization using ISerializable so our derived class need special constructor for deserialization


public SerializableDictionary(SerializationInfo info, StreamingContext context):base(info,context)
        { 
        }





So the implementation of SeriliazableDictionary<T> which can be serializable as Xml and also in binary formate is given bellow.


[Serializable]
[XmlRoot("Dictionary")]


public class SerializableDictionary<VT>: Dictionary<string,VT>,IXmlSerializable
{ 
public SerializableDictionary( SerializationInfo info, StreamingContext context):base(info,context){} public SerializableDictionary(){} public XmlSchema GetSchema(){         return (null);       }
   public void ReadXml(XmlReader reader)    {      Boolean wasEmpty = reader.IsEmptyElement;      reader.Read();      if (wasEmpty)       {          return;       }      while (reader.NodeType!= XmlNodeType.EndElement)       {          if (reader.Name == "Item")           {            String key = reader.GetAttribute("Key");            Type type = Type.GetType(reader.GetAttribute("TypeName"));            reader.Read();            if (type != null)            {              Add(key, (VT)new XmlSerializer(type).Deserialize(reader));            }            else            {              reader.Skip();            }            reader.ReadEndElement();            reader.MoveToContent();           }        }        reader.ReadEndElement();   }   public void WriteXml(XmlWriter writer)   {    for (int i=0;i<Keys.Count;i++)    {      string key =Keys.ElementAt(i);      VT value= this.ElementAt(i).Value;      writer.WriteStartElement("Item");      writer.WriteAttributeString("Key", key);      writer.WriteAttributeString(string.Empty,"TypeName",string.Empty, value.GetType().AssemblyQualifiedName);      new XmlSerializer(value.GetType()).Serialize(writer, value);      writer.WriteEndElement();    }   } }

No comments:

Post a Comment