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();    }   } }

.NET Utility class for getting application name of a site

 

In our application we needed to find out application name of a site for routing. One solution for finding out application name from URL using regular expression. but VirtualPathUtility class of .NET make it easy to get application name by using relative path. VirtualPathUtility class provides utlity methos for common operations involving virtual paths. We do not know with which name our application would be deployed. so for constructing URL we use ‘~’ for relative path. So VirtualPathUtility.ToAbsolute(“~”) give me the absolute path ‘/Website’ were my website URL is http://localhost/Website. Also for getting relative path of a resource from a user control of a site you can use VirtualPathUtility.MakeRelative(Request.Path, "~/scripts/jquery-1.4.1.js");