Serialization is the process of converting information into a byte stream that can be stored or transferred. To serialize an object, first create a stream object. Then create a BinaryFormatter object and call the BinaryFormatter.Serialize method. To deserialize an object, follow the same steps but call the BinaryFormatter.Deserialize method.
BinaryFormatter Located in the System.Runtime.Serialization.Formatters.Binary namespace, this formatter is the most efficient way to serialize objects that will be read by only .NET Framework–based applications.
SoapFormatter Located in the System.Runtime.Serialization.Formatters.Soap namespace, this XML-based formatter is the most reliable way to serialize objects that will be transmitted across a network or read by non–.NET Framework applications. Objects serialized with SoapFormatter are more likely to successfully traverse firewalls than BinaryFormatter.
To create a class that can be serialized, add the Serializable attribute. You can also use attributes to disable serialization of specific members.
SoapFormatter provides a less efficient, but more interoperable, alternative to the BinaryFormatter class.
To use SoapFormatter, follow the same process as you would for BinaryFormatter, but use the System.Runtime.Serialization.Formatters.Soap.SoapFormatter class.
You can control SoapFormatter serialization by using attributes to specify the names of serialized elements and to specify whether a member is serialized as an XML element or as an XML attribute.
It is a good practice to make all classes serializable even if you do not immediately require serialization. You should disable serialization for calculated and temporary members.
Serialization outputs an object as a series of bytes, whereas deserialization reads a serialized object and defines the value of an object. Most custom classes can be serialized by simply adding the Serializable attribute. In some cases, you might be able to improve efficiency or provide for changes to the structure of classes by modifying your class to change the default serialization behavior.
Guidelines for Serialization
- When in doubt, mark a class as Serializable. Even if you do not need to serialize it now, you might need to do so later, or another developer might need to serialize a derived class or a class that includes your class as a member.
- Mark calculated or temporary members as NonSerialized. For example, if you track the current thread ID in a member variable, the thread ID is likely to be invalid upon deserialization. Therefore, you should not store it.
- Use SoapFormatter when you require portability. Use BinaryFormatter for greatest efficiency.
Best Practices for Version Compatibility
- Never remove a serialized field.
- Never apply the NonSerialized attribute to a field if the attribute was not applied to the field in a previous version.
- Never change the name or type of a serialized field.
- When adding a new serialized field, apply the OptionalField attribute.
- When removing a NonSerialized attribute from a field that was not serializable in a previous version, apply the OptionalField attribute.
- For all optional fields, set meaningful defaults using the serialization callbacks unless 0 or null are acceptable defaults.
XML serialization provides interoperability to communicate with different platforms and flexibility to conform to an XML schema.
XML serialization cannot be used to serialize private data or object graphs.
To serialize an object, first create a stream, TextWriter, or XmlWriter. Then create an XmlSerializer object and call the XmlSerializer.Serialize method. To deserialize an object, follow the same steps but call the XmlSerializer.Deserialize method.
To create a class that can be serialized as XML, specify the class and all members as public and create a parameterless constructor.
You can control XML serialization by using attributes. Attributes can change the names of elements, serialize members as XML attributes rather than as XML elements, and exclude members from serialization.
Use the Xsd.exe tool to create a class that automatically conforms to an XML schema when serialized.
Data sets, arrays, collections, and instances of an XmlElement or XmlNode class can all be serialized with XmlSerializer.
XML serialization provides a way to store and transfer objects using open standards. XML serialization can be customized to fit the exact requirements of an XML schema, making it simple to convert objects into XML documents and back into objects.
You can implement ISerializable to perform custom serialization.
BinaryFormatter provides four events that you can use to control parts of the serialization process: OnSerializing, OnSerialized, OnDeserializing, and OnDeserialized.
The StreamingContext class, an instance of which is provided to methods called during serialization events, gives you information about the origin or planned destination of the serialization process. The method performing serialization must specify this information for it to be useful.
Although few developers require total control over serialization, you can implement the IFormatter interface to create custom formatters.
Custom serialization is required in situations where classes contain complex information, significant changes have occurred to the structure of a class between different versions, or where you need complete control over how information is stored. You can perform custom serialization by implementing the ISerializable interface and by responding to serialization events.