Serialization in .Net is one of the more useful features in .Net that I use all the time. Serialization – especially XML Serialization – makes it essentially trivial to write out the content of an object to a file, stream very easily. This is useful to pass data between applications, but also a great simple mechanism for saving and reloading state of applications. In fact, I use Serialization for just about every application to store a number of configuration settings easily.
Although Serialization is pretty straight forward, today I got tired of having to write the same serialization code over and over again. It's not much code, but remembering the stream and formatting options always required me looking this stuff up and fumbling for a few minutes in the docs or for an old sample.
Today, after having done this for the nth time, I added a couple of generic serialization methods to my utility class libraries. The result are the following two static methods:
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
…
/// <summary>
/// Serializes an object instance to a file.
/// </summary>
/// <param name="Instance">the object instance to serialize</param>
/// <param name="Filename"></param>
/// <param name="BinarySerialization">determines whether XML serialization or binary serialization is used</param>
/// <returns></returns>
public static bool SerializeObject(object Instance, string Filename,
bool BinarySerialization)
{
bool retVal = true;
if (!BinarySerialization)
{
XmlTextWriter writer = null;
try
{
XmlSerializer serializer =
new XmlSerializer(Instance.GetType());
// Create an XmlTextWriter using a FileStream.
Stream fs = new FileStream(Filename, FileMode.Create);
writer = new XmlTextWriter(fs, new UTF8Encoding());
writer.Formatting = Formatting.Indented;
writer.IndentChar = ' ';
writer.Indentation = 3;
// Serialize using the XmlTextWriter.
serializer.Serialize(writer,Instance);
}
catch(Exception)
{
retVal = false;
}
finally
{
if (writer != null)
writer.Close();
}
}
else
{
Stream fs = null;
try
{
BinaryFormatter serializer = new BinaryFormatter();
fs = new FileStream(Filename, FileMode.Create);
serializer.Serialize(fs,Instance);
}
catch
{
retVal = false;
}
finally
{
if (fs != null)
fs.Close();
}
}
return retVal;
}
/// <summary>
/// Deserializes an object from file and returns a reference.
/// </summary>
/// <param name="Filename">name of the file to serialize to</param>
/// <param name="ObjectType">The Type of the object. Use typeof(yourobject class)</param>
/// <param name="BinarySerialization">determines whether we use Xml or Binary serialization</param>
/// <returns>Instance of the deserialized object or null. Must be cast to your object type</returns>
public static object DeSerializeObject(string Filename,Type ObjectType,
bool BinarySerialization)
{
object Instance = null;
if (!BinarySerialization)
{
XmlReader reader = null;
XmlSerializer serializer = null;
FileStream fs = null;
try
{
// Create an instance of the XmlSerializer specifying type and namespace.
serializer = new XmlSerializer(ObjectType);
// A FileStream is needed to read the XML document.
fs = new FileStream(Filename, FileMode.Open);
reader = new XmlTextReader(fs);
Instance = serializer.Deserialize(reader);
}
catch
{
return null;
}
finally
{
if (fs != null)
fs.Close();
if (reader != null)
reader.Close();
}
}
else
{
BinaryFormatter serializer = null;
FileStream fs = null;
try
{
serializer = new BinaryFormatter();
fs = new FileStream(Filename, FileMode.Open);
Instance = serializer.Deserialize(fs);
}
catch
{
return null;
}
finally
{
if (fs != null)
fs.Close();
}
}
return Instance;
}
These methods work with file output for serialization since that is the most common scenario I run into as manual serialization usually ends up being a persistence mechanism. It's trivial to work with strings if you need to (see below)...
Both of these methods are static so they require that you pass in the type that you’re dealing with. My primary purpose originally was to serialize and deserialize my business objects, but it is impossible to deserialize an object into the this reference – you always must have variable to deserialize into.
The following example actually serialize an object you might use something like this:
wwUtils.SerializeObject(Configuration,"d:\\temp\\xConf.xml",false);
Then to reload the object:
Configuration = (ConfigClass) DeSerializeObject("d:\\temp\\xConf.xml",
typeof(ConfigClass),false);
Much easier to deal with if you do this on a regular basis. If you need to return a deserialized object in string format you can cheat a little and dump the output to file and read it back in. This is not the most efficient way to do this (a MemoryStream would work better), but it requires very little work:
public string ToXml()
{
wwUtils.SerializeObject(this,TFile,false);
System.IO.StreamReader sr = new System.IO.StreamReader(TFile);
string XML = sr.ReadToEnd();
sr.Close();
File.Delete(TFile);
return XML;
}
Remember that any objects that you want to serialize must be marked with the [Serialiazable()] attribute or inherit from MarshalByRefObject. The object also may not contain any subobjects that may not serialize. For example, a DataRow cannot be serialized. IComponent.ISite cannot be serialized – if you have objects that include non-serializable subobjects serialization will fail. The workaround for this is to make those specific members of the class as non-serializable.
[XmlIgnore] // DataRows can't serialize
public DataRow DataRow
{
get { return this.oDataRow; }
set { this.oDataRow = value; }
}
[NonSerialized]
DataRow oDataRow = null ;
You can use XMLIgnore on properties persisted into XML serialization. Note that this has no effect on binary serialization. For binary serialization use the [NonSerialized] attribute on field values, which causes field values not be persisted and passed forward.
Among other things serialization is a great way to persist data between application runs. I also find it invaluable to use for debugging as I can simply dump state of an object to disk at runtime and review later which can come in handy at times.
Other Posts you might also like