Search

Friday, 16 September 2011

Serialization 101 - Part II: SOAP Serialization

Introduction

In Part I of this series, we took a brief look at how to perform binary serialization to persist the state of objects in our application to some form of permanent storage medium and then retrieve them again at a later point in time

In this article we are going to take a quick look at SOAP serialization. This article is going to be quite brief as I don't intend going into a massive amount of detail, mainly because SOAP serialization is now generally considered to be superseded by XML serialization, which we will look at in Part III.

Upgrading the Farmyard

Continuing with the sample farmyard application we looked at in Part I, how do we go about the process of upgrading our software to support saving in SOAP format, as well as binary? Well, as I hinted at in Part I, SOAP serialization uses the same mechanism as binary serialization.

Therefore, as all the relevant classes have already been decorated with the appropriate attributes to support serialization, all that should be required is to substitute the BinaryFormatter object for a SoapFormatter object when saving the data:

// C#
public enum FileFormat { Binary = 1, Soap = 2 }

using (Stream fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None))
{
    IFormatter formatter;
    switch ((FileFormat)saveFarmyardDialog.FilterIndex)
    {
        case FileFormat.Binary: formatter = new BinaryFormatter(); break;
        case FileFormat.Soap: formatter = new SoapFormatter(); break;
        default: formatter = new BinaryFormatter(); break;
    }
    formatter.Serialize(fileStream, this.farmyard);
}
' Visual Basic
Public Enum FileFormat
    Binary = 1
    Soap = 2
End Enum

Using fileStream As Stream = New FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None)
    Dim formatter As IFormatter
    Select Case DirectCast(saveFarmyardDialog.FilterIndex, FileFormat)
        Case FileFormat.Binary
            formatter = New BinaryFormatter()
        Case FileFormat.Soap
            formatter = New SoapFormatter()
        Case Else
            formatter = New BinaryFormatter()
    End Select
    formatter.Serialize(fileStream, farmyard)
End Using

...and for loading the data:

// C#
using (Stream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
    IFormatter formatter;
    switch ((FileFormat)loadFarmyardDialog.FilterIndex)
    {
        case FileFormat.Binary: formatter = new BinaryFormatter(); break;
        case FileFormat.Soap: formatter = new SoapFormatter(); break;
        default: formatter = new BinaryFormatter(); break;
    }
    farmyard = (Farmyard)formatter.Deserialize(fileStream);
}
' Visual Basic
Using FileStream As Stream = New FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)
    Dim formatter As IFormatter
    Select Case DirectCast(loadFarmyardDialog.FilterIndex, FileFormat)
        Case FileFormat.Binary
            formatter = New BinaryFormatter()
        Case FileFormat.Soap
            formatter = New SoapFormatter()
        Case Else
            formatter = New BinaryFormatter()
    End Select
    farmyard = DirectCast(formatter.Deserialize(FileStream), Farmyard)
End Using

As you can see, we use a simple switch...case statement, based on the selected file format from the load/save dialog, to determine whether to instantiate a BinaryFormatter or a SoapFormatter object. As before, we are serializing our objects to disk; however if we were using SOAP serialization in a real-world application, we would more likely be serializing to a NetworkStream.

And that it is it, that should be all that is needed to for our application to work. Well, actually no. Try and run the application as it is, and you will get a dirty great exception when you try to serialize using the SoapFormatter. The reason? Apparently the SoapFormatter does not support the serialization of generics, and is therefore throwing its toys out of the pram when it encounters our List<Animal> object which we have used to underpin our farmyard.

As a (not too elegant) workaround, I have used the following code to shuttle the data to and from a non-generic collection when serializing and de-serializing:

// C#
[NonSerialized]
private List<Animal> animals;

private ArrayList animalsForSerialization;

[OnSerializing]
private void OnSerializing(StreamingContext context)
{
    animalsForSerialization = new ArrayList();
    foreach (Animal animal in animals)
        animalsForSerialization.Add(animal);
}

[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
    NewDay();
    animals = new List<Animal>();
    foreach (Animal animal in animalsForSerialization)
        animals.Add(animal);
    animalsForSerialization = null;
}
' Visual Basic
<NonSerialized()>
Private animals As List(Of Animal)

Private animalsForSerialization As ArrayList

<OnSerializing()>
Private Sub OnSerializing(ByVal context As StreamingContext)
    animalsForSerialization = New ArrayList
    For Each animal As Animal In animals
        animalsForSerialization.Add(animal)
    Next
End Sub


<OnDeserialized()>
Private Sub OnDeserialized(ByVal context As StreamingContext)
    NewDay()
    For Each animal As Animal In animalsForSerialization
        animals.Add(animal)
    Next
    animalsForSerialization = Nothing
End Sub

Note the use of the OnSerializing and OnDeserialized attributes we discussed in Part I to control the serialization process. Also, as a result of our change, we won't be able to load any farmyards which were saved with the previous version of the application. A more elegant solution would, of course, allow for backward compatibility

Summary

SOAP serialization uses the same mechanism as binary serialization; however one major limitation is the inability to serialize generics.

The source code for the farmyard application can be downloaded here.

Next: XML Serialization

2 comments:

  1. Great!This article is creative,there are a lot of new idea,it gives me inspiration.I think I will also inspired by you and think about more new ideas.

    ----------------------------------------------------------
    New Style Wedding Dresses
    Column Wedding Dresses
    Wedding Dresses with Sleeves
    New Style Flower Girl Dresses

    ReplyDelete
  2. Your article is very smooth, very lively written, using the grammar very well, giving us a lot of fun .. Keep it up! lyj

    ReplyDelete