Serialization is the process of persisting the current state of an object into a stream in such a way that it contains all information to be deserialized into the same object when needed. You’d do this typically when you’re dealing with remoting services, or when working with web services.
There are two types of serialization in the .NET Framework:
- Serialization by creating object graphs
- XML serialization
We’ll deal with XML serialization in the next post, let’s focus on object graphs first. Object graphs are mathematical formulas that describe relationships between your serialized objects. I wouldn’t force the theory of serialization furthermore, if you are interested, there’s a great chapter about serialization in Pro C# 2008 and the .NET Framework, which I recommended at the beginning of these posts. I’d like to take it practical, and introduce the classes, interfaces and attributes that play role in the process.
Easy, that’s not much. There are four serialization-related interfaces:
- IFormatter: any custom serialization formatters should implement this interface. It defines two methods: object Deserialize(Stream) and void Serialize(Stream, object). There’s some help for implementers in the form of the Formatter class, which implements this interface and adds further functionality.
- IFormatterConverter: this interface adds methods to parse data in the SerializationInfo class.
- IDeserializationCallback: specifies a method to call when the deserialization process is completed. Use the serialization attributes specified later instead.
- ISerializable: provides a method (void GetObjectData(SerializationInfo, StreamingContext) to help a class control its own serialization. Use the serialization attributes specified later instead. This interface also requires a constructor (SerializationInfo, StreamingContext), which should be marked as protected.
It is generally a better idea to use the serialization-related attributes instead of ISerializable. Here are they:
- Serializable: you must mark your class as Serializable when you intend it to participate in the serialization process. Note that when you’re using XmlSerializer, you don’t have to use this attribute, however, it’s a good practice to do so.
- NonSerialized: mark a field with this attribute to prevent it from being serialized.
- OnSerializing: mark a method void(StreamingContext) to make it fire just before serialization occurs.
- OnSerialization, OnDeserializing, OnDeserialized: playing exactly the same role with the same pattern as OnSerializing.
Last but not least, let’s see the remaining classes and structures:
- StreamingContext: this structure describes the source and destination of a given serialized stream.
- SerializationInfo: you can get a SerializationInfo by implementing the ISerializable interface. Through its methods, you are able to retrieve and modify data from the current serialized stream.
There are some more classes that plays part in custom serialization, but I don’t think they would be too important. If you are interested, check out Niall Merrigan’s related checklist.