Serialization

Published Fri, Mar 17 2006 20:26 | Paul June

I know that this is an old age technology in .Net. But I was surprised that some C# programmers still don’t know about serialization. So I’m creating this blog for the ones who still hasn’t got any idea on serialization. But if you already know this, then just skip this blog entry.

Here’s a FAQ about serialization.

What is serialization?
Well, according to MSDN, “as the process of storing the state of an object instance to a storage medium”. So why do we need to store a class in an external storage? The reason for this is that, sometimes we need to communicate across between applications. And sometimes, it’s a lot easier if we can pass objects between two separate application domains.

Why use serialization?
Just like as said earlier, sometimes when you need to pass objects between two applications, you can’t pass it through memory coz two different applications resides in two different domains. So you must find a way to store it externally so that the other application could read the external file and recreate your class.

How do you serialize a class?
All you have to do is mark your class as serializable. To do this just place the serializable keyword enclosed in angle bars before the declaration of your class:

[Serializable]
public class MyObject {
   public int n1 = 0;
   public int n2 = 0;
   public String str = null;
}

This is the basic serializable class. When you serialize the class. All of its private and public properties would also be saved. Now, to serialize a class, you must have a serializer. To explain it better, Here’s an example:

MyObject obj = new MyObject();
obj.n1 = 1;
obj.n2 = 24;
obj.str = "Some String";
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin",
                         FileMode.Create,
                         FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();

This sample writes your class into a File names “MyFile.bin”.

After serializing, what should I do?
After serializing the class, you should deserialize it for you to restore the state of the saved class. Here’s a sample:
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin",
                          FileMode.Open,
                          FileAccess.Read,
                          FileShare.Read);
MyObject obj = (MyObject) formatter.Deserialize(fromStream);
stream.Close();

// Here's the proof
Console.WriteLine("n1: {0}", obj.n1);
Console.WriteLine("n2: {0}", obj.n2);
Console.WriteLine("str: {0}", obj.str);

In the previous example, we are using the BinaryFormatter as the serializer for our class. The BinaryFormatter class serializes our class into a file. But its pretty useful to serialize our class into an xml stream. This is the case of Webservices. To serialize a class into an xml stream, you’ll have to use the SoapFormatter instead of BinaryFormatter.

What if I don’t like to include some properties during serialization?
To exclude some properties, just mark them as NonSerialized. Here’s a sample:

[Serializable]
public class MyObject
{
   public int n1;
   [NonSerialized] public int n2;
   public String str;
}

This process is called Selective Serialization.

What about the ISerializable Interface?
The ISerializable interface is used when your doing Custom Serialization. Wondering what difference it is compared to Selective Serialization? Well, when your class is implementing the ISerializable interface, you will have the power to set values to your variables during serialization. This is pretty much useful when a value in your class would be invalid after deserialization, but you need to initialize its value. You must be also wondering if why not just place the initialization code in your constructor? The answer is simple, during deserialization your constructor would not be called. So how to implement ISerializable? Here’s a sample:

Serializable]
public class MyObject : ISerializable
{
   public int n1;
   public int n2;
   public String str;

   public MyObject()
   {
   }

     protected MyObject(SerializationInfo info, StreamingContext context)
   {
     n1 = info.GetInt32("i");
     n2 = info.GetInt32("j");
     str = info.GetString("k");
   }

   public virtual void GetObjectData(SerializationInfo info,
StreamingContext context)
   {
      info.AddValue("i", n1);
      info.AddValue("j", n2);
      info.AddValue("k", str);
   }
}

There are two things to consider when implementing the ISerializable interface. You should implement a special constructor which happens during deserialization. And also the GetObjectData method, this method is called during the serialization process.

When should I use Serialization?
A straightforward answer, always. You should mark your classes serializable as often as possible. Coz you might not know that the user of your class might design to inherit your class and serialize it. Hmmm. I kinda forgot to say that you cannot serialize an object if the base class is not serializable. Sorry for that.

So during your design phase, you should identify the classes that you think its users would serialize. To be safe, you can mark all of your class into serializables.

I hope this clarifies any issue about serialization. Cheers!

Filed under:

Leave a Comment

Name:  
Website: