Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to serialize an object which is NOT marked as 'Serializable' using a surrogate.

0.00/5 (No votes)
2 May 2005 1  
Serialize an object which is NOT marked as 'Serializable' using a surrogate.

Introduction

This article describes how to serialize an object which is not marked as 'Serializable' using a surrogate.

Background

Serialization is a process of converting an object in memory into a byte stream, suitable for transportation across the wire and persisting in a stable storage. Only an object that is marked as serializable can be serialized. The problem here is to serialize an object which is not marked as serializable.

Using the code

We will look into a step-by-step approach of "How to serialize an object which is not marked as 'Serializable' using a surrogate". For this purpose, consider a simple class called Vehicle, whose source code is not available. The code for the class Vehicle is shown below...

The Vehicle class is as follows:

    /// <SUMMARY>

    /// NOTE: It is assumed for this demo that the source code for this class

    /// is not available and this class cannot be marked as '[Serializable]'.

    /// </SUMMARY>

    public class Vehicle 
    {
        /// <SUMMARY>

        /// Make of the vehicle.

        /// </SUMMARY>

        private string _make;

        /// <SUMMARY>

        /// Model of the vehicle.

        /// </SUMMARY>

        private string _model;

        public string Make
        {
            get
            {
                return _make;
            }

            set
            {
                _make = value;
            }
        }

        public string Model
        {
            get
            {
                return _model;
            }

            set
            {
                _model = value;
            }
        }
    }

In order to serialize this class, a new class called VehicleSurrogate needs to be written. See the source code of the class VehicleSurrogate below...

    public class VehicleSurrogate : ISerializationSurrogate
    {
        /// This method is part of the interface ISerializationSurrogate

        public void GetObjectData(object obj, SerializationInfo info, 
                                                StreamingContext context)
        {
            Vehicle vehicle = obj as Vehicle;
            // Set the vehicle object's properties

            info.AddValue("Make", vehicle.Make);
            info.AddValue("Model", vehicle.Model);
        }

        /// This method is part of the interface ISerializationSurrogate

        public object SetObjectData(object obj, SerializationInfo info, 
                   StreamingContext context, ISurrogateSelector selector)
        {
            // Restore the vehicle object's properties

            Vehicle vehicle = obj as Vehicle;
            vehicle.Make  = info.GetString("Make");
            vehicle.Model = info.GetString("Model");
            
            // This is ignored.

            return null;
        }

The interface ISerializationSurrogate provides two methods needed to serialize and de-serializable objects. The properties can be set/retrieved as and when required. Now!! As for the client code, in order to put all this into use... look at the method SerializeUsingSurrogate():

        public void SerializeUsingSurrogate()
        {
            try
            {
                // Create a new instance of the vehicle class.

                // NOTE: It is assuming for this demo that the source 

                // code for this class

                // is not available.

                Vehicle vehicle = new Vehicle();
                vehicle.Make = "Cadillac";
                vehicle.Model = "2005";
                
                // 1. Create an instance of a Soap Formatter.

                IFormatter formatter = new SoapFormatter();

                // 2. Construct a SurrogateSelector object

                SurrogateSelector ss = new SurrogateSelector();

                // 3. Construct an instance of our serialization surrogate type

                VehicleSurrogate vss = new VehicleSurrogate();

                // 4. Tell the surrogate selector to use our object when a 

                //    Vehicle object is serialized/deserialized.

                // NOTE: AddSurrogate can be called multiple times to register

                // more types with their associated surrogate types

                ss.AddSurrogate(typeof(Vehicle), 
                    new StreamingContext(StreamingContextStates.All), vss);
                                
                // Creating a byte array to hold the data.

                byte[] bData = new byte[1024];

                MemoryStream memoryStream = new MemoryStream(bData);
                TextWriter textWriter = new StreamWriter(@"C:\Vehicle.xml");

                // 5. Have the formatter use our surrogate selector

                formatter.SurrogateSelector = ss;

                // Try to serialize a Vehicle object

                formatter.Serialize(memoryStream, vehicle);
                
                // Create a buffer to hold the data.

                StringBuilder buffer = new StringBuilder();

                for(int count = 0; count < bData.Length; count++)
                {
                    if ( bData[count] != '\0')
                    {
                        // Convert the char stream data to string.

                        buffer.Append( Convert.ToChar(bData[count]));
                    }
                }

                textWriter.WriteLine(buffer.ToString() );

                // clean up.

                textWriter.Close();
                buffer = null;
            }
            catch(Exception)
            {
                // Check for exception in case of a fault.

            }
        }

Let us walkthrough this code step-by-step...

  1. Create an instance of the Vehicle object and set its properties.
  2. Create an instance of the SoapFormatter object, this shall be used to add surrogate selectors.
  3. Create an instance of the SurrogateSelector.
  4. Construct an instance of our serialization surrogate type VehicleSurrogate.
  5. Add our surrogates using the method AddSurrogate of the SurrogateSelector object.
  6. Have the formatter use our surrogate selector using the formatter.SurrogateSelector.
  7. Try to serialize the Vehicle object.
  8. Create a buffer to hold the serialized data using StringBuilder object.

Points of Interest

A 'ISerializationSurrogate' can be used to provide custom serialization for objects which are not marked as serializable and for those whose source code is not available.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here