使用 Protobuf-net 进行 Silverlight 二进制序列化





5.00/5 (8投票s)
如何将纯 .NET 对象类序列化为快速二进制数据
引言
本文向您展示如何在 Silverlight 中将纯 .NET 对象类序列化为快速二进制数据。
背景
Silverlight 不提供纯二进制对象序列化。 虽然 DataContractSerializer
和 XmlSerializer
是很好的序列化基础设施,但这些类都基于 XML。 The CustomBinarySerializer approach 是一种很好的二进制实现方法,但它需要为每个业务对象创建方便的类。
Protobuf-net
Protobuf-net 是 Google Protobuf 的 C# 实现组件之一,它提供更紧凑和快速的纯 .NET 对象类的二进制序列化。 此外,该组件还支持 Silverlight 版本,使我们能够使用 SocketAsyncEventArgs
类,将一些数据保存和加载到本地磁盘、通过 HTTP 的远程 WCF 服务器或低级 TCP/IP 套接字。 它为原始类型生成原始级别的 byte[]
,但 Silverlight 序列化器基于 XML 数据。
Protobuf-csharp-port 是 Protobuf 的另一个很棒的 C# 版本。 它遵循 Java 实现的大部分标准 API 和编码模式。 它为每个业务类使用工具生成的编解码器。 但是,我选择 Protobuf-net 作为 Protobuf 的基本二进制编解码器引擎,因为它遵循基本的 .NET 架构。
它使用属性反射,但其性能足够快。 此外,该引擎使我们能够更轻松地使用干净的纯业务对象类和基本流类。 在 Silverlight 中使用 Protobuf-net 程序集很容易,而使用 Silverlight 中的 Protobuf-csharp-port 则需要进行一些代码修复任务。
Silverlight IsolatedStorage(独立存储)
在 Silverlight 中,我们可以使用 IsolatedStorage
将一些数据存储到我们的本地硬盘。 存储空间和位置受到限制,但 Silverlight 浏览器外环境可以解锁该限制。
我们将使用 IsolatedStorage
来保存和加载我们的数据,并使用 Protobuf-Net 二进制序列化。
Using the Code
设置项目
我们将使用 VS2008 SP1 和 Silverlight 3。 我们应该添加带有网站测试选项的 Silverlight 应用程序项目模板。 以下图像是我们项目的最终布局。
您可以在任何“Silverlight 类库或应用程序”项目类型中使用 protobuf-net 程序集。 此 SLBufferSerializer
是一个 Silverlight 应用程序项目,带有 VS2008 自动生成的 Silverlight ASP.NET 网站。

确保在网站中设置起始页以使用 F5。 请参阅此图片,了解如何设置网站项目属性。
Person 业务类 (Person.cs)
让我们使用 ProtoBuf-net 的“ProtoContract
”和“ProtoMember
”属性创建 Person
纯类。 这种方法与 XMLSerializer
方法非常相似。 以下属性的数字是 Google 的 protobuf 所需的顺序。
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;}
}
}
设计一个显示 XAML 页面 (MainPage.xaml)
这是在设计主显示 XAML 页面后,Visual Studio 中的设计预览。 您可以在本文的源代码中查看详细的 XAML 代码。

IsolatedStorage 助手方法 (MainPage.xaml.cs)
这些是将 Protobuf-net 序列化到 IsolatedStorage
的助手方法。 编解码器引擎基本上使用 Stream 实现,因此 IsolatedStorageStream
类也可用。
您还可以将这些方法放置到另一个 static
助手类
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);
}
}
}
实现代码隐藏逻辑 (MainPage.xaml.cs)
初始化一个 person
实例。 让我们保存和加载 person
实例的序列化数据。
...
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)
{
}
}
...
}
}
最终的 Silverlight 结果屏幕
这是反序列化后执行的屏幕。

参考文献
有关更多信息,请点击以下链接