Archive

Posts Tagged ‘Serialization’

Silverlight binary serialization using Protobuf-net

April 14, 2010 2 comments

 

Introduction

This article shows you how to serialize a pure .NET object classes to a fast binary data in Silverlight.

 

Background

Silverlight don’t provide pure binary object serialization. Although the DataContractSerializer and the XmlSerializer are nice serialization infra, these classes are based just XML. The CustomBinarySerializer approach is good binary implementation way, but this way needs to make handy classes for each business objects.

 

Protobuf-net

The Protobuf-net is one of the Google Protobuf C# implementation components, which provides more compact and fast binary serialization of pure .NET object classes. Also the component support Silverlight version that enables us to save and load some data to the local disk or remote WCF server via HTTP.

Protobuf-csharp-port is another great C# version of the Protobuf. It follows most standard API’s and coding patterns of Java implementation. It uses tool generated codec for each business classes. But I selected Protobuf-net as the base binary codec engine of the Protobuf as it follows the basic .NET architecture .

It uses attribute reflection but the performance of it is fast enough. Also the engine enables us to use clean pure business object classes and basic stream classes more easily. It is easy to use the Protobuf-net assembly in Silverlight, while using the Protobuf-csharp-port in the Silverlight needs several code-fix tasks.

Silverlight IsolatedStorage

In Silverlight, We can store some data to our local hard disk using IsolatedStorage. The storage space and location are limited, but the limit can be unlocked of Silverlight Out-Of-Browser environment.

We will use IsolatedStorage for saving and loading our data with Protobuf-Net binary serialization.

Implementation Step1 : Setup project

We will use VS2008 sp1 and Silverlight 3. We should add Silverlight application project template with web site test option. This following image is the final layout of our project.

projectlayout_thumb2

Implementation Step2 : Person business class

Let’s make the Person class with ‘ProtoContract’ and ‘ProtoMember’ attributes of ProtoBuf-net.

using System; 
using ProtoBuf; 

namespace SLBufferSerializer 
{ 
    [ProtoContract] 
    public class Person { 
        [ProtoMember(1)] 
        public int Id {get;set;} 
        [ProtoMember(2)] 
        public string Name { get; set; } 
        [ProtoMember(3)] 
        public Address Address {get;set;} 
    } 
    [ProtoContract] 
    public class Address { 
        [ProtoMember(1)] 
        public string Line1 {get;set;} 
        [ProtoMember(2)] 
        public string Line2 {get;set;} 
    } 
}

Implementation Step3 : Design a display xaml page

This is design preview in Visual Studio after design a main display xaml page.

xamlpreview

Let’s check the xaml code.

<UserControl x:Class="SLBufferSerializer.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot">
        <StackPanel Width="200" Margin="20">
            <TextBlock x:Name="txtStatus" Text="Ready"></TextBlock>
            <Button x:Name="btnTest" Content="Click" Click="btnTest_Click"></Button>
            <Grid Background="White">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="35*" />
                    <ColumnDefinition Width="65*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                
                <TextBlock Grid.Column="0" Grid.Row="0" Text="Id"></TextBlock>
                <TextBlock Grid.Column="1" Grid.Row="0" x:Name="txt1"></TextBlock>
                <TextBlock Grid.Column="0" Grid.Row="1" Text="Name"></TextBlock>
                <TextBlock Grid.Column="1" Grid.Row="1" x:Name="txt2"></TextBlock>
                <TextBlock Grid.Column="0" Grid.Row="2" Text="Address1"></TextBlock>
                <TextBlock Grid.Column="1" Grid.Row="2" x:Name="txt3"></TextBlock>
                <TextBlock Grid.Column="0" Grid.Row="3" Text="Address2"></TextBlock>
                <TextBlock Grid.Column="1" Grid.Row="4" x:Name="txt4"></TextBlock>
                
            </Grid>
        </StackPanel>
  </Grid>
</UserControl>

Implementation Step4 : IsolatedStorage helper methods

These are helper methods for Protobuf-net serialization to the IsolatedStorage. The codec engine uses Stream implementation basically, so IsolatedStorageStream class is also available.

        private static void SaveToStorage<T>(string filePath, T instance)
        {
            using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filePath, FileMode.CreateNew, storage))
                {
                    Serializer.Serialize<T>(stream, instance);
                }
            }
        }

        private static T LoadFromStorage<T>(string filePath)
        {
            using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, storage))
                {
                    return Serializer.Deserialize<T>(stream);
                }
            }
        }

Implementation Step5 : Implementing code-behind logics

Initialize a person instance. Let us to make save and load the serialized data of the person instance.

...
using ProtoBuf;

namespace SLBufferSerializer
{
    public partial class MainPage : UserControl
    {
        private readonly string fileName = "test.txt";

        public MainPage()
        {
            InitializeComponent();
            this.ProtobufSerialize();
        }

        private void ProtobufSerialize()
        {
            var person = new Person
            {
                Id = 12345,
                Name = "Fred",
                Address = new Address
                {
                    Line1 = "Flat 1",
                    Line2 = "The Meadows"
                }
            };

            try
            {
                SaveToStorage<Person>(fileName, person);
            }
            catch (IsolatedStorageException)
            {

            }
        }

        private void btnTest_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Person person = LoadFromStorage<Person>(fileName);

                this.txtStatus.Text = "De-Serialized....";
                this.txt1.Text = person.Id.ToString();
                this.txt2.Text = person.Name;
                this.txt3.Text = person.Address.Line1;
                this.txt4.Text = person.Address.Line2;
            }
            catch (IsolatedStorageException)
            {

            }
        }
	...
    }
}

The final silverlight result screen

Here is the executed screen after de-serialization.

SilverlightProtobufNet

You can download the source project file at here.

Before running this project, you should set the static start page of the test web site.

References

For more information, follow this link.

Advertisements