.

Wednesday, June 25, 2008

Serialization in .NET

What Is Serialization in .NET ?

Serialization is the process of producing an object into a series of bytes that can be saved in the memory, in a file or on the disk. Consider you have a class which has several members of different data types. But we use object of that class as a whole. In case we wanted to write a object on a file, we would need to serialize the object into bytes and write on the file, and if our requirement was to read from a file we would deserialize the bytes written in the file to a object form and use in our program. Thus the common use of serialization is to save an object and of deserialization is to retrieve that object when required. You could think of another use of serialization, remember the remoting, web services and SOAP, they all require data transfer in bytes. .NET Framework supports built in serialization. We can accomplish using two methods:

  • Using System.Runtime.Serialization namespace

  • Using System.Xml.serialization

Using System.Runtime.Serialization

This mechanism of implementing serialization is quite generic. It requires you to create a stream and a formatter. The stream, as name suggests would contain the bytes of the serialized objects and the formatter does the functionality. .NET supports some built in formatters, you can even create your own custom formatter. It is the IFormatter interface that implements all the formatters. The two formatters used are:

  • BinaryFormatter

  • SoapFormatter

Using BinaryFormatter : It is as simple as shown in function below. myfun is a function that will write to file the contents of object of type "myclass" obj.

public static void myfun (myclass obj, String filename)
{
Stream s = File.OpenWrite (filename);
BinaryFormatter f = new BinaryFormatter ( );
f.Serialize (s, obj);
s.Close ( );
}

But it is to note here that while defining "myclass", you must use the "Serializable" keyword as shown below:

[Serializable]
public class myclass
{
}

Using SoapFormatter: It is similar to implement as binary formatter, all you need to do is, replace BinaryFormatter in the method code above to SoapFormatter. The output file could be easily read using a text editor, if you use SoapFormatter rather than BinaryFormatter.

It is to note that if you do not want certain members of the class to be serialized than, you should use "NonSerialized" keyword with that member. Example:

[Serializable]
public class myclass
{
[NonSerialized]
private string myvar;
}

Using System.Xml.Serialization

This is another way to implement serialization. Using this namespace we can map the classes to a given XML representation in particular format. This is the main code that does the functionality:

XmlSerializer var = new XmlSerializer ( typeof ( myclass ) );
StringWriter str = new StringWriter ( );
var.Serialize (var, obj); //where obj is the object of type myclass

Its just with two lines, you have created an XML representation. If you have an XML schema for the required format, we can generate .NET classes corresponding to the complex types in the schema with the Framework's XSD schema definition tool. It is to note that XmlSerializer permits any classes derived from System.IO.Stream, System.IO.TextWriter or System.Xml.XmlWriter.

You can even declare the root element of the generated class by using one of the attributes, XmlRootAttribute as shown below:

usingSystem.Xml.Serialization;

[XmlRootAttribute(Name = "Students", IsNullable = false)]
public class myclass
{
}

Example to create a serialize method:

Suppose the structure of "myclass" is:

public class myclass
{
public string myname;
public string myprofession;
}

It is to note here that all members must be declared public/

void Serializemyclass()
{
XmlSerializer var = new XmlSerializer ( typeof ( myclass ) );
XmlTextWriter str = new XmlTextWriter ("myclass.xml", System.Text.Encoding.UTF8);
writer.Formatting = Formatting.Indented; //for formatting
myclass obj = new myclass();
myclass.myname = "John"
myclass.myprofession = "Software Engineer";
var.Serialize(str, obj);
str.Close();
}

The output XML file for the above serialized object would be

xml version="1.0" encoding="utf-8"?>
<myclass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<myname> John myname>
<mypofession> Software Engineer mypofession>
myclass>

Similar to NonSerialized, we have XmlIgnore in XmlSerializer, to disable serializability of some member. It is used exactly in the same way, just replace the NonSerialized keyword with XmlIgnore.

Custom Serialization

The .Net Framework has support for custom serialization. This can be accomplished by implementing the ISerializable interface. Custom Serialization is more flexible than the two discussed above. If a class requires custom serialization it would implement ISerializable interface and would have :

  • A method GetObjectData ( a part of the interface)

  • A constructor that takes two parameters, an object of SerializationInfo, and StreamingContext.

Example:

public class myclass:ISerializable
{
private string myname;
private string myprofession;

protected myclass ( SerializationInfo var1, StreamingContext var2)
{
this.myname =var1.GetString("myname");
this.myprofession =var1.GetString("myprofession");
}

void ISerializable.GetObjectData (SerializationInfo var1, StreamingContext var2)
{
var1.AddValue("myname",this.myname);
var1.AddValue("myprofession",this.myprofession);
}
}

GetObjectData is called by the framework to indicate about serialization. The object serializes itself into the SerializationInfo object which is then passed to GetObjectData as a parameter. SerializationInfo holds the serialized object. The AddInfo method is creates a name-value pair that is serialized to the stream. Use this method to serialize only the members you want to serialize.

No comments:

.