October 23, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Serialization Part 2: Version-Tolerant Serialization

  • June 29, 2005
  • By Mark Strawmyer
  • Send Email »
  • More Articles »

VTS Attributes

A couple of simple attributes that help control serialization will help you with the problem above:

·         NonSerializedAttribute – ignore the field altogether

·         OptionalFieldAttribute – ignore the field if not present

One simple way to work around the versioning issue would be to use the NonSerialized attribute. If you placed the attribute on your contactTitle field, it would be ignored when you try to deserialize the Customer from the prior binary file.

The following is a modified code snippet for the Customer object:

[NonSerialized()]

private string contactTitle = "";

public string ContactTitle

{

get { return this.contactTitle; }

set { this.contactTitle = value; }

}

That is all well and good as long as you have no intention of using the new property in newly serialized versions of your object. It does not help in the case where you want to serialize/deserialize both versions of your object, meaning use the ContactTitle if it’s there and ignore if it’s not. You can use the OptionalFieldAttribute instead.

The following is a modified code snippet for the Customer object:

[OptionalField()]

private string contactTitle = "";

public string ContactTitle

{

get { return this.contactTitle; }

set { this.contactTitle = value; }

}

This is a modified code snippet for your testing program:

using (FileStream fileStream = new FileStream(@"C:\mytest.bin", FileMode.Open))

{

        BinaryFormatter formatter = new BinaryFormatter();

        customer = (Customer)formatter.Deserialize(fileStream);

}

 

if (customer.ContactTitle == null || customer.ContactTitle.Length == 0 )

{

Console.Write("{0} - {1}", customer.CompanyName, customer.ContactName);

}

else

{

Console.Write("{0} - {1} – {2}", customer.CompanyName,

customer.ContactName, customer.ContactTitle);

}

Now if you deserialize your Customer using the new version, it will ignore the contactTitle since it is not available in the previously created file. You can verify that it will indeed read the ContactTitle (if it is present) by creating another serialized version that does have it set, and read it back in using the same code above. My code to create a new serialized version of the test file looked something like this:

using System.IO;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

using System.Runtime.Serialization.Formatters;

 

class Program

{

static void Main(string[] args)

{

Customer customer = new Customer();

customer.CompanyName = "Alfreds Futterkiste";

customer.ContactName = "Maria Anders";

customer.ContactTitle = "Sales Representative";

 

using (FileStream fileStream = new FileStream(@"C:\mytest-v2.bin", FileMode.Create))

{

        BinaryFormatter formatter = new BinaryFormatter();

        formatter.Serialize(fileStream, customer);

}

customer.Clear();

using (FileStream fileStream = new FileStream(@"C:\mytest-v2.bin", FileMode.Open))

{

        BinaryFormatter formatter = new BinaryFormatter();

        customer = (Customer)formatter.Deserialize(fileStream);

}

 

if (customer.ContactTitle == null || customer.ContactTitle.Length == 0 )

{

Console.Write("{0} - {1}", customer.CompanyName, customer.ContactName);

}

else

{

Console.Write("{0} - {1} – {2}", customer.CompanyName,

customer.ContactName, customer.ContactTitle);

}

}

By commenting out the file-creation part and changing the read part between mytest.bin and mytest-v2.bin, you should be able to prove that you can read both versions into the new Customer object.

More Control of the Serialization Process

In the past, the only way to get full control of the serialization process was to implement the ISerializable interface, which equates to more code and more complexity. Additional attributes are available to allow you more control without having to go as far as implementing the ISerializable interface. Each of those attributes can be placed on a method and has the following impact:   

·         OnDeserializingAttribute – called during deserialization

·         OnDeserializedAttribute – called immediately after deserialization is complete

·         OnSerializingAttribute – called during serialization

·         OnSerializedAttribute – called immediately after serialization is complete

This offers another middle-of-the-road solution to provide even more control without requiring you to go to the full extent of implementing the ISerializable interface.

The following is an additional code snippet for the Customer object:

[OnDeserializing()]

void OnDeserializingTest(StreamingContext context)

{

        // Do something here during deserialization...

}

 

[OnDeserialized()]

void OnDeserializedTest(StreamingContext context)

{

        // Do something here after deserialization...

}

 

[OnSerializing()]

void OnSerializingTest(StreamingContext context)

{

        // Do something here during serialization...

}

 

[OnSerialized()]

void OnSerializedTest(StreamingContext context)

{

        // Do something here after serialization...

}

A Big Improvement in Serialization

You have now seen an introduction to the version-tolerant serialization that is in the pending release of the 2.0 version of the Microsoft .NET Framework. This is a big improvement in serialization, especially for those who want some control of the process but don’t want to have to fully implement ISerializable and all of the baggage that it carries with it such as extra code.

Future Columns

The topic of the next column is yet to be determined. If you have something in particular that you would like to see explained here you could reach me at mstrawmyer@crowechizek.com

About the Author

Mark Strawmyer, MCSD, MCSE, MCDBA is a Senior Architect of .NET applications for large and mid-size organizations. Mark is a technology leader with Crowe Chizek in Indianapolis, Indiana. He specializes in architecture, design, and development of Microsoft-based solutions. Mark was honored to be named a Microsoft MVP for application development with C# for the second year in a row. You can reach Mark at mstrawmyer@crowechizek.com.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel