Friday, March 25, 2011

How to Customizing the Serialization and the Deserialization Process in BinaryFormatter.

ISerializable interface:
•    Implement the GetObjectData method.
•    Populate the SerializationInfo parameter when it is called by the Serialize method.
Serialization events:
   
•    Use the OnSerializingAttribute attribute to mark a method that runs before serialization commences.
•    Use the OnSerializedAttribute attribute to mark a method that runs when serialization completes.

You can customize the process that you use to serialize an object by implementing the System.Runtime.Serialization.ISerializable interface or by applying the OnSerializing and OnSerializedAttribute attributes to members of a type, specifying methods to be run when the members are serialized. These techniques are useful if you must perform some additional or nonstandard processing as part of the serialization process.

Implementing the ISerializable Interface to Control Serialization:

The ISerializable interface enables you to control exactly which fields in a class are serialized and how they are serialized. The ISerializable interface consists of a single method that is called GetObjectData, which the formatter calls when it serializes an object, overriding the part of the default process that determines which data to serialize. Before it invokes GetObjectData, the formatter performs some initialization, sets up some data structures, and writes out data such as the assembly information to the serialization stream. The GetObjectData method takes two parameters: a SerializationInfo object and a StreamingContext structure.

Customizing the Deserialization Process.
Custom class requirements:
•    Add a deserialization constructor.
•    Populate the object with the data in the SerializationInfo parameter.

Deserialization events:
•    Use the OnDeserializingAttribute attribute to mark a method that runs before deserialization commences.
•    Use the OnDeserializedAttribute attribute to mark a method that runs when deserialization completes.

The following example display below:

using System;
using System.Runtime;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace    ExampleCustomSerialization
{
    [Serializable]
    class TestClass : ISerializable, IDeserializationCallback
    {
        private string name;
        private int tosquare;

        public string Name
        {
            get
            {
                return this.name;
            }
            private set
            {
                this.name = value;
            }
        }

        public int ToSquare
        {
            get
            {
                return this.tosquare;
            }
            private set
            {
                this.tosquare = value;
            }
        }


        public int Squared;

        public TestClass(string name, int toSquare)
        {
            Name = name;
            ToSquare = toSquare;
            ComputeSquare();
        }

        public TestClass(SerializationInfo info, StreamingContext context)
        {
            // Deserialization Constructor

            Name = info.GetString("Name");
            ToSquare = info.GetInt32("ToSquare");
            Console.WriteLine("Deserializing constructor");
            ComputeSquare();
        }

        private void ComputeSquare()
        {
            Squared = ToSquare * ToSquare;
        }

        [OnSerializing]
        private void OnSerializing(StreamingContext context)
        {
            Console.WriteLine("OnSerializing fired.");
        }

        [OnSerialized]
        private void OnSerialized(StreamingContext context)
        {
            Console.WriteLine("OnSerialized fired.");
        }

        [OnDeserializing]
        private void OnDeserializing(StreamingContext context)
        {
            Console.WriteLine("OnDeserializing fired.");
        }

        [OnDeserialized]
        private void OnDeserialized(StreamingContext context)
        {
            Console.WriteLine("OnDeserialized fired.");
        }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            Console.WriteLine("Serializing...");
            info.AddValue("Name", Name);
            info.AddValue("ToSquare", ToSquare);
        }


        void IDeserializationCallback.OnDeserialization(object sender)
        {
            Console.WriteLine("IDeserializationCallback.OnDeserialization method.");
            //ComputeSquare();
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            TestClass tc = new TestClass("Test", 3);
            FileStream fs = new FileStream("Serialized.txt",     FileMode.Create);
            BinaryFormatter bf = new BinaryFormatter();

            bf.Serialize(fs, tc);
            fs.Close();
            tc = null;

            //FileStream fs = new FileStream("Serialized.txt", FileMode.Open);
            //BinaryFormatter bf = new BinaryFormatter();
            //TestClass tc = (TestClass)bf.Deserialize(fs);

            //Console.WriteLine("Squared = " + tc.Squared);
            //Console.WriteLine("Squared = " + tc.Name);

No comments:

Recent Posts