Fredrik Normén's Blog - NSQUARED²
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Microsoft Most Valuable Professional
     .Net Framework - ASP.Net - Architecture - Development
NOTE: This list of posts will only list the 15 latest posts, to see the rest, select from the Archives located in the menu to the left. The RSS will only list the 10 lastest posts.
Versioning Tolerance Serailization

Category:  .Net Framework 2.0

During the Friday I was thinking of versioning and serialization issues. So I decided to write something about how to use versioning tolerance serialization with .Net 2.0.

 

Assume you have created a class and serialized it and you have created a new version of the class. If you try to deserialize the old class by using the new class, an exception will be thrown, because of a versioning problem. You can solve this problem now with .Net 2.0 by using the new OptionalFieldAttribute added to the System.Runtime.Serialization namespace.

 

Take a look at the following code:

 

[Serializable]

public class Address

{

    private string _street;

 

    public string Street

    {

          get { return this._street; }

          set { this._street = value; }

    }

}

 

Let’s assume you have serialized this class, and you need to create a new version of the class where you need to add a new property to the Address class to specify a country.

 

The next version of your Address class will look something like this:

 

[Serializable]

public class Address

{

    private string _street;

    private string _country;

 

    public string Street

    {

          get { return this._street; }

          set { this._street = value; }

    }

 

    public string Country

    {

          get { return this._country; }

          set { this._street = country; }

    }

}

 

If you now try deserialize the Address object, that has been serialized earlier with the old version of the Address class, an exception will be thrown, because there will be a versioning conflict. To solve this problem you have to use versioning tolerance serailization (VST). As I mention before this could be done with the OptionalFieldAttribute. With the use of the OptinoalFieldAttribute, your new Address class should look like this:

 

[Serializable]

public class Address

{

    private string _street;

 

    [OptionalField(VersionAdded = 2)]

    private string _country;

 

    public string Street

    {

          get { return this._street; }

          set { this._street = value; }

    }

 

    public string Country

    {

          get { return this._country; }

          set { this._street = country; }

    }

}

 

As you can see in the code above, the OptionalFieldAttribute is added to the new field, not to the property. The VersionAdded argument of the attribute is for mark (if I’m not totally wrong) which version of the Address class this new field is added to the class. If you now do a deserialization, no exception will be thrown.

 

There will be more features for handling version tolerance serialization when Beta 2 of VS 2005 is released, for example you should be able to tell which properties that are removed sine the last version etc.

 

Something that is also new to .Net 2.0 is the following attributes:

 

OnDeserializing

OnDeserialized

OnSerializing

OnSerialized

 

Use them to mark the methods that would be executed during the serialization and deserialization of the class.

 

Here is an example:

 

[Serializable]

public class Address

{

    private string _street;

 

    [OptionalField(VersionAdded = 2)]

    private string _country;

 

    public Address() {}

 

    public string Street

    {

          get { return this._street; }

          set { this._street = value; }

    }

 

    public string Country

    {

          get { return this._country; }

          set { this._street = country; }

    }

 

    #region Serialization Processing

 

    [OnDeserializing]

    private void OnDeserializing(StreamingContext context)

    {

          this._country = null;

    }

 

    [OnDeserialized]

    private void OnDeserialized(StreamingContext context)

    {

          if (this._country == null)

             this._country = “Sweden”;

    }

 

    [OnSerializing]

    private void OnSerializing(StreamingContext context)

    {

    }

 

    [OnSerialized]

    private void OnSerialized(StreamingContext context)

    {

    }

 

    #endregion

}

 

If you take a look at the method OnDeserialzed in the example above, you can see that the Country field will be set to a default value “Sweden” if the field is null. This will be done after the deserailization is done.  Bu using those new attributes, you can do some logic before and after serialization or when you do the deserailization.

Posted: Sunday, September 05, 2004 - 10:46 GMT+1    Print     E-mail    Comments (1)
   fredrik.nsquared2.com - 2007