Last Updated: 12/2003

Serialization

Topics

XML Serialization vs. Binary Serialization

Binary Serialization XML Serialization
  • Efficient (binary) storage format
  • Closed format
  • Contains Type information
  • Well suited for .NET Remoting
  • Can serialize private fields, so does not serialize properties
  • Requires the serialized type(s) to be marked with the [System.Serializable] attribute
  • Fields marked with the [System.NonSerialized] attribute are not serialized
  • Programmer can override the default serialization by implementing ISerializable and a special constructor
  • Has 'StreamingContext' indicating whether the serialization is to/from file, cross process, cross app domain, remoting etc.
  • Text (XML) storage format
  • Open format
  • Does not contain Type information
  • Well suited for Web Services
  • Cannot serialize private fields, but does serialize non read-only / write-only properties)
  • Fields and properties marked with the [System.Xml.Serialization.XmlIgnore] attribute are not serialized
  • Programmer can override the default serialization by using attributes at design time and, to a limited extent, by supplying 'overrides' at run time
  • Format is not adjusted for context
  • The XmlSerializer class creates temporary C# files in the temp directory at run-time which it compiles into a DLL. In theory, there are security issues with this.
  • Requires a public default constructor (i.e. one that takes no arguments)

Note: There is a 3rd serializer, Soap, that is not discussed here.

Back to Topic List 


XML Serialization - Base Example

using System;
using System.IO;  // For StringWriter & Reader
using System.Xml.Serialization; // For XmlSerializer

namespace ConsoleApplication1 {
      public class Item {
            public string Description;
            public int Quantity;

             // Public default constructor as required by XmlSerializer
            public Item() {}
 
            public Item(string description, int quantity) {
                  this.Description = description;
                  this.Quantity = quantity;
            }
      }

       class Class1 {
            static void Main() {
                  // Give us something to serialize
                  Item[] writeItems = new Item[] { new Item("Fish", 10),
                      new
Item("Beans", 20), new Item("Jeans", 5) };

                  // Write items out to string
                  TextWriter textWriter = new StringWriter();
                  XmlSerializer serializer = new XmlSerializer(typeof(Item[]));
                  serializer.Serialize(textWriter, writeItems);
                  string xml = textWriter.ToString();
                  Console.WriteLine(xml);

                   // Read items back in
                  TextReader textReader = new StringReader(xml);
                  Item[] readItems = (Item[]) serializer.Deserialize(textReader); 

                  // Show it worked
     
            foreach(Item item in readItems) Console.WriteLine("{0} {1}",
                        item.Description, item.Quantity);
            }
      }
}

Back to Topic List 

 

XML Serialization - Attribute Example

Change the Item class to include the attributes in bold:

      [XmlRootAttribute("Root")]
      public class Item {

            [XmlElement("GoodsDescription")]
            public string Description;

            [XmlAttribute("NumberInStock")]
            public int Quantity;

            [XmlIgnore]
            public int notSerialized;

            // Public default constructor as required by XmlSerializer
            public Item() {}
 
            public Item(string description, int quantity) {
                  this.Description = description;
                  this.Quantity = quantity;
            }
      }

XML Outputted Before Changes XML Outputted After Changes
<Item>
    <Description>Fish</Description>
    <Quantity>10</Quantity>
</Item>
<Item>
    <Description>Beans</Description>
    <Quantity>20</Quantity>
</Item>
<Item>
    <Description>Jeans</Description>
    <Quantity>5</Quantity>
</Item>
<Root NumberInStock="10">
    <GoodsDescription>Fish</GoodsDescription>
</Root>
<Root NumberInStock="20">
    <GoodsDescription>Beans</GoodsDescription>
</Root>
<Root NumberInStock="5">
    <GoodsDescription>Jeans</GoodsDescription>
</Root>

Note:
Because we did Item[] instead of Item the actual sample produced <Item> not <Root>. This could be a bug as it works fine when we do individual Items or Items as a collection.

Back to Topic List 


Binary Serialization - Base Example

using System;     // For Serializable attribute
using System.IO;  // For FileStream class
using System.Runtime.Serialization.Formatters.Binary; // For BinaryFormatter class

namespace ConsoleApplication1 {
      [System.Serializable]
      public class Item {
            public string Description;
            public int Quantity;
            public Item(string description, int quantity) {
                  this.Description = description;
                  this.Quantity = quantity;
            }
      }

      class Class1 {
            static void Main() {
                  // Give us something to serialize
                  Item[] writeItems = new Item[] { new Item("Fish", 10),
                      new
Item("Beans", 20), new Item("Jeans", 5) }; 

                  // Write items out to file
                  FileStream fs = new FileStream("test.bin", FileMode.Create);
                  BinaryFormatter bf = new BinaryFormatter();
                  bf.Serialize(fs, writeItems);
                  fs.Close(); 

                  // Read items back in
                  fs = new FileStream("test.bin", FileMode.Open);
                  Item[] readItems = (Item[]) bf.Deserialize(fs);
                  fs.Close();

                  // Show it worked
                  foreach(Item item in readItems) Console.WriteLine("{0} {1}",
                      item.Description, item.Quantity);
            }
      }
}

Back to Topic List 

 

Binary Serialization - ISerialization Example

To convert the example to use ISerializable, change the item class in the base example as follows:

Change:
    public
class Item {
to:
    public class Item : ISerializable {

Add the following methods to the Item class body:
    // ISerializable requires a method that returns the data to be serialized
   
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
          info.AddValue("description", this.Description);
          info.AddValue("quantity", this.Quantity);
          info.AddValue("WhenWeDidThis", DateTime.Now);
          Console.WriteLine("GetObjectData called!");
    }

   // Although optional, ISerializable doesn't make sense without this sort of constructor
   protected Item(SerializationInfo info, StreamingContext context) {
       this.Description = info.GetString("description");
       this.Quantity = info.GetInt32("quantity");
       Console.WriteLine("Constructor called for data that was serialized at {0}",
            info.GetDateTime("WhenWeDidThis"));
   }

No other changes to class1 are required.

Back to Topic List