Section 9.4. Serialization and Streams


9.4. Serialization and Streams

Using a file stream isn't mandatoryyou can serialize an object's state into any type of stream, such as a network or memory stream. Example 9-12 demonstrates how to serialize and deserialize an object to and from a memory stream, using the same definitions as in Example 9-4.

Example 9-12. Serialization and deserialization using a memory stream
 MyClass obj = new MyClass(  ); obj.Number1 = 123; IGenericFormatter formatter = new GenericBinaryFormatter(  ); //Create a memory stream Stream stream = new MemoryStream(  ); using(stream) {    formatter.Serialize(stream,obj);    obj = null;    stream.Position = 0; //Seek to the start of the memory stream    obj = formatter.Deserialize<MyClass>(stream); } Debug.Assert(obj.Number1 == 123);

.NET remoting uses a memory stream when marshaling an object by value across app domains. Marshaling by value is covered in Chapter 10.


You can actually use a memory stream to clone a serializable object, too. Example 9-13 shows the static Clone( ) method of the SerializationUtil static helper class.

Example 9-13. Cloning a serializable object
 public static class SerializationUtil {    static public T Clone<T>(T source)    {       Debug.Assert(typeof(T).IsSerializable);       IGenericFormatter formatter = new GenericBinaryFormatter(  );       Stream stream = new MemoryStream(  );       using(stream)       {          formatter.Serialize(stream,source);          stream.Seek(0,SeekOrigin.Begin);          T clone = formatter.Deserialize<T>(stream);          return clone;       }    }    //Rest of SerializationUtil }

The Clone( ) method first verifies that the object passed in for cloning is serializable, by obtaining the type of the source object. The type Type provides a Boolean read-only property called IsSerializable, which returns true if the type has the Serializable attribute. Clone( ) then uses the GenericBinaryFormatter helper class to serialize and deserialize the object into and out of the memory stream. Clone( ) returns the deserialized object (in essence, a deep copy of the source object). Using Clone( ) is straightforward:

     [Serializable]     public class MyClass     {...}         MyClass obj1 = new MyClass(  );     MyClass obj2 = SerializationUtil.Clone(obj1);

You can use SerializationUtil.Clone( ) as an easy way to implement the ICloneable interface:


     [Serializable]     public class MyClass : ICloneable     {        public object Clone(  )        {           return SerializationUtil.Clone(this);        }     }

9.4.1. Serializing Multiple Objects

A noteworthy aspect of using streams in serialization is that there are no limits to the number of objects or types you can serialize into a stream. It all depends on the way you manage the stream and the sequence in which you write and read the information. For example, to serialize additional objects into the same stream, all you need to do is continue to write to the stream with the formatter. Of course, you have to deserialize the objects in exactly the same order in which you serialized them, as shown in Example 9-14. You can use the same formatter object or create a new one.

Example 9-14. Serializing multiple objects to the same stream
 [Serializable] public class MyClass {...} [Serializable] public class MyOtherClass {...} MyClass obj1 = new MyClass(  ); MyClass obj2 = new MyClass(  ); MyOtherClass obj3 = new MyOtherClass(  ); IGenericFormatter formatter = new GenericBinaryFormatter(  ); Stream stream; stream = new FileStream(@"C:\temp\obj.bin",FileMode.Create,FileAccess.Write); using(stream) {    formatter.Serialize(stream,obj1);    formatter.Serialize(stream,obj2);    formatter.Serialize(stream,obj3); } obj1 = obj2 = null; obj3 = null; //Later on: stream = new FileStream(@"C:\temp\obj.bin",FileMode.Open,FileAccess.Read); using(stream) { obj1 = formatter.Deserialize<MyClass>(stream); obj2 = formatter.Deserialize<MyClass>(stream); obj3 = formatter.Deserialize<MyOtherClass>(stream); }

You can achieve a similar effect with memory streams, too, as long as the memory stream automatically allocates additional memory.

Another option is to append the state of additional objects to an existing storage. In the case of a file stream, open the file in append mode:

     MyClass obj1 = new MyClass(  );     MyClass obj2 = new MyClass(  );     IGenericFormatter formatter = new GenericBinaryFormatter(  );     //Create a new file     Stream stream;     stream = new FileStream(@"C:\temp\obj.bin",FileMode.Create,FileAccess.Write);     using(stream)     {        formatter.Serialize(stream,obj1);     }     //Append another object     stream = new FileStream(@"C:\temp\obj.bin",FileMode.Append,FileAccess.Write);     using(stream)     {        formatter.Serialize(stream,obj2);     }



Programming. NET Components
Programming .NET Components, 2nd Edition
ISBN: 0596102070
EAN: 2147483647
Year: 2003
Pages: 145
Authors: Juval Lowy

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net