Serialization and optional elements

Posted on October 14, 2005 // 0 Comments

Using a new feature called Version Tolerant Serialization in .NET 2, it becomes possible to change class definitions and still deal with old serialized data versions after an application has been updated. This is actually extremely easy to do. Consider this code:

Now say you have deployed version 1 of your application with this class definition and used serialization to save instances of class Test to some kind of storage. Users of your application have megabytes of data stored away in that specific format.

Now you continue developing your application and you find the need to add properties to Test. The problem is, once you do that, you’ll no longer be able to deserialize the earlier version of the class, resulting in huge data loss for your users! Version Tolerant Serialization is the feature that comes to the rescue here. You can now define your new class version like this:

[Serializable]
public class Test {
string name;
public string Name {
get { return name; }
set { name = value; }
}
int newVal;
[OptionalField]
public int NewVal {
get { return newVal; }
set { newVal = value; }
}
bool marker;
[OptionalField]
public bool Marker {
get { return marker; }
set { marker = value; }
}
[OnDeserializing]
void Deserializing(StreamingContext context) {
// We get here before data is actually written to our properties
// So we set some default values for the optional properties.
newVal = 42;
marker = false;
}
[OnDeserialized]
void Deserialized(StreamingContext context) {
// We get here when data has been written to all the properties
// that were found during deserialization, which may not have been
// all we have in case an old storage format was used.
// So we can now analyze what's happened and fix up what's necessary.
if (!marker) {
// . . .
}
}
}

In many cases, dedicated fixup code may not really be necessary, but it’s certainly possible to work with older data definitions in this way, at least for most kinds of changes. There are also corresponding attributes OnSerializing and OnSerialized, in case a hook into the serialization process is needed as well.