Wednesday, November 10, 2010

Object Serialization in .NET

Serialization and its counter-process (Deserialization) is a mechanism to "package" an object for transport to another application or process.

You might want to send a stream of data over a web service, store it in a database, or need some type of interop way to transport an object across system.

The two main methods of serialization in .NET is the Binary and XML.  In a binary serialization, the object is converted to (get this) a binary stream; which is the fastest method of serialization.  Alternately with the XML serialization the stream is plain text which is better for interop.  One key note is that XML doesn't preserve the data type as well as binary but binary is really only useful for .NET to .NET type communication/transport.

Prerequisites to serialization... Serialization is not "free" in the sense that you have to do some work to make your classes/objects serializable.  The easiest way to do this is to mark your class with the attribute as shown here:

    [Serializable]
    public sealed class SomeObject
    {
        public int n1 = 0;
    }

This works because basic data types like int, string, etc .NET already knows how to serialize. However, if I had another custom class it would need to be marked as Seralizable as well.  This can has a cascading effect (all objects in the tree must be serializable [or marked as NonSerialized]) so keep that in mind when looking into this solution.

As I just alluded to if you want something to skip the serialization step then it needs to be marked as [NonSerialized] but keep in mind that object will be null when you Deserialize your object.

A simple example of how to serialize an object:

//Required namespaces
using System.IO; //required for stream
using System.Runtime.Serialization.Formatters.Binary; //required for binary formatter
using System.Runtime.Serialization; //required for Formatter Interface

SomeObject obj = new SomeObject();

IFormatter formatter = new BinaryFormatter();

Stream stream = new FileStream("MyFile.bin",
                                     FileMode.Create,
                                     FileAccess.Write, FileShare.None);

formatter.Serialize(stream, obj);
stream.Close();

As you see above we use a formatter. In this case we used the Binary Formatter but could have used the XML Formatter as well.  The formatter as the name suggests converts the object into the specified serial format and puts it into a stream.

In this case I put the object into a file but I could modify the code and store it in a string or some other container.

As I mentioned earlier now with this object stored in a stream/file/whatever we can now do with it what we please.  For our example, we'll say that this binary goes into a folder for processing by a Windows Service.  In the service it is very simple to pull the object back into memory and start working with it...

FileStream fs = new FileStream("MyFile.bin", FileMode.Open);
BinaryFormatter readFormatter = new BinaryFormatter();
SomeObject serialObj = (SomeObject)formatter.Deserialize(fs);

Just like that we now have our object back and can start working with it.

Limitations...  Some things to keep in mind when doing serialization ... I already mentioned that data that is marked as NonSerialized will be blank/null in the object.  But also keep in mind deserializing an object is not the same as creating a new object.  Therefore, the constructor don't be called.

Also, only public information is serialized.

Custom Serialization... I didn't touch on it but you can inherit the ISerializable interface and invoke your own GetObjectData method to write your own custom serialization for an object.  By default, you don't need to do this unless you have special requirements for the output of the serialization (say your formatting your XML to a schema that another system will consume, etc).

No comments:

Post a Comment