在 .NET Compact Framework 2.0 中使用序列化

1. 序列化概述

序列化(Serialization)是.NET平台最酷的特性之一。利用序列化技术,可以实现对象的备份和还原。序列化可以将内存中的对象(或对象图)序列化为数据流,并保存到磁盘上进行持久化;还可以将数据流反序列化为对象,实现对象的还原。序列化技术在分布式系统的数据传输中得到充分的利用,如:XML Web Service 利用XML序列化实现跨平台,.NET Remoting 则用到了二进制序列化和SOAP序列化。

.NET Compact Framework 2.0 支持XML序列化,不支持二进制序列化和SOAP序列化。而 .NET Compact Framework 1.0 连XML序列化都不支持。不过 OpenNETCF 1.x 为 .NET CF 1.0 实现了一个XML序列化的类,这个类在 OpenNETCF.Xml.dll 程序集中可以找到。

2. XML 序列化

在 .NET CF 2.0 中使用XML序列化很简单,跟 .NET Framework 中的一样。

// XML序列化 Customer 数组
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
  Customer[] customers 
= GetCustomers(); //从数据库或远程服务器获取客户
  System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(Customer));
  ser.Serialize(ms, customers); 

  
byte[] buffer = ms.ToArray();
  
// 获取XML文档的内容
  string xml = System.Text.Encoding.ASCII.GetString(buffer , 0, buffer .Length);
}

// XML反序列化 Customer 数组
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer))
{
  System.Xml.Serialization.XmlSerializer ser 
= new System.Xml.Serialization.XmlSerializer(typeof(Customer));
  Customer[] customers 
= ser.Deserialize(ms) as Customer[]; 
}


以上示例将对象序列化后,写入内存流中。你可以换成文件流(FileStream),这样就可以实现对象的持久化。

3. 二进制序列化

从理论上说,二进制序列化无论是性能还是序列化后的数据流大小都比XML序列化更具优势,这个我曾经在《实战 Web Service 压缩传输》的PPT和Demo 中深入分析过。.NET CF 2.0 并没有提供二进制序列化的类,如果你想在 .NET CF 2.0 中进行二进制序列化,可以通过第三方的开源组件 CompactFormatter 来实现。我在去年5月份就介绍过 CompactFormatter,详细请看 让 .NET Compact Framework 支持 Binnary Serialization。由于 CompactFormatter 同时支持 .NET CF 和 .NET Framework,我们可以将 CompactFormatter 序列化后的数据流可以转换为 byte[],并传输到服务器后进行反序列化。

今天我简单介绍一下 CompactFormatter 的使用,用来跟上面的XML序列化进行比较。

为了让一个实体类能够被 CompactFormatter 序列化,首先需要将这个实体类加上 [CompactFormatter.Attributes.Serializable()] 特性。

[CompactFormatter.Attributes.Serializable()]
public class Customer {
  
public Customer() { }

  
}


然后重写 Equals 方法。

public override bool Equals(object obj)
{
  
if (!obj.GetType().Equals(typeof(Customer)))
  {
    
return false;
  }
  
else
  {
    Customer answer 
= (Customer)obj;
    
return (answer.ID == ID && answer.Name == Name);
  }
}


就如上面的代码中,我将实体类 Customer 加上 [CompactFormatter.Attributes.Serializable()] 特性,并重写了它的 Equals 方法,现在可以使用 CompactFormatter 进行序列化了。

// 二进制序列化 Customer 数组
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
  CompactFormatter.CompactFormatter ser 
= new CompactFormatter.CompactFormatter();
  ser.Serialize(ms, customers); 

  
byte[] buffer = ms.ToArray();
}

// 二进制反序列化 Customer 数组
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer))
{
  CompactFormatter.CompactFormatter ser 
= new CompactFormatter.CompactFormatter();
  customers 
= ser.Deserialize(ms) as Customer[];
}

 

4. 序列化示例

为了比较 .NET CF 2.0 下的XML序列化和 CompactFormatter 的二进制序列化,我做了一个示例,可以用它来测试两种序列化的性能。我会用两种序列化方法对一个包含1000个 Customer 对象的数组进行序列化和反序列化,并记录两种方法各自耗费的时间和序列化后数据流的字节大小。

具体操作是在 Visual Studio 2005 中采用调试模式将示例程序部署到 Pocket PC 2003 仿真器(最新的V2版本)中并运行。先执行XML序列化,接着执行XML反序列化,然后退出程序。在调试模式下重新启动示例程序,先后执行二进制序列化和二进制反序列化。测试结果如下:

XML序列化
字节数:207870
耗时:6秒

XML反序列化
耗时:4秒

二进制序列化
字节数:200867
耗时:3秒

二进制反序列化
耗时:2秒

从测试结果看,CompactFormatter 的二进制序列化速度比XML序列化要快1倍,反序列化也是快1倍。但是序列化后的数据流大小却相差不多,这点我有点失望。

5. 总结

在现实应用中,CompactFormatter 可以搭配 SharpZipLib 和 WS-Attachment 使用,从而实现低速网络下(GPRS/CDMA)的高性能数据传输。关于 WS-Attachment 的使用可以参考我之前写的文章 在 Windows Mobile 使用 WS-Attachment 传输二进制数据。我接下来会对 Windows Mobile 下的压缩组件进行评测,感兴趣的朋友请关注我的博客。

示例代码下载:SerializationMobile.rar

作者:黎波
博客:http://upto.cnblogs.com/
日期:2007年4月20日

本文属于作者原创,转载请注明作者和出处,谢谢合作!

posted @ 2007-04-20 12:05 黎波 阅读(3747) 评论(17)  编辑 收藏 网摘 所属分类: Mobile Samples.NET CF

  回复  引用  查看    
#1楼2007-04-20 13:29 | redmoon      
好文章,值得学习!
  回复  引用    
#2楼2007-04-20 16:38 | 轩辕[未注册用户]
黎波大哥,你好!

我现在还是有点问题想问你下,我是石家庄一个即将毕业的大学生。学习.NET CF将近一年了。主要是因为参加MEDC2006,感觉到.net cf的应用在以后会有很大的作为,所以改ASP.NET到.NET CF的。现在即将毕业了,而我也一直在研究微软的LOB的代码示例,为的就是当北京找工作可以有具体的项目实践。但是我这些天在各大招聘网站上发现几乎都是没有招.net cf的。唉,现在不知道何去何从了。


  回复  引用    
#3楼2007-04-20 16:54 | 轩辕[未注册用户]
现在我虽然在学习WIN 32,但是感觉至少一年的时间才可以掌握。这对于马上就要毕业的我来说,是根本没有办法找到WIN CE开发工作。上次也联系了中软强网,他们叫我带具体的项目过去,但是因为我现在石家庄,而且考虑到还是有必要把C#,ADO.NET等各方面的知识在复习下,所以思量前后就没有去。其实我现在是这样想的,如果真是在北京找不到.net cf的工作话,我就决定翻译一本关于sql server CE的书籍。

现在几乎所有的职位都是要工作经验,虽然我也当过.net方面的助教,但是实际的项目经验还真是不多。希望大哥可以在工作和面试的经验方面可以给于一些指点,谢谢!


  回复  引用    
#4楼2007-04-20 17:39 | 航天奇侠
.net 才是王道,现在真的感觉到.net的能力了。

  回复  引用  查看    
#5楼[楼主]2007-04-20 18:22 | Bob Li      
@ 轩辕
北京移动开发的工作机会还是比较多。如果你选择了.NET CF,也就是选择了.NET企业应用开发的方向,这个方向需要掌握的技术不仅仅是.NET CF的,ASP.NET和Smart Client都需要掌握,特别是Smart Client,还有SQL Server。所以如果你确实找不到.NET CF的工作,可以先做做别的,这样对你的发展很有利。

  回复  引用  查看    
#6楼2007-04-22 20:23 | Leepy      
关注中。
请问个问题好么?最近在做WAP网站,有个问题,就是如何让网站上的图片下载到自己的手机(这里指非智能手机)上去呢?
听说有些服务接口,可以直接连接,但是测试没有通过,我的Sim卡是移动的。
另外,网站已经设在固定IP上了。

  回复  引用  查看    
#7楼[楼主]2007-04-22 21:45 | Bob Li      
@Leepy
这个帮不到你,我没有接触过WAP开发:(

  回复  引用  查看    
#8楼2007-04-22 22:22 | Leepy      
请问能否提供一份组件SharpZipLib,发现下载不下来!
sunleepy@gmail.com, 麻烦了!

  回复  引用  查看    
#9楼[楼主]2007-04-23 11:00 | Bob Li      
  回复  引用    
#10楼2007-04-23 16:23 | 轩辕[未注册用户]
谢谢黎波大哥的指点,现在正在努力中,虽然.net cf的工作不好走,我还是决定先往智能客户端这方面发展下。
  回复  引用    
#11楼2007-05-15 15:50 | zsz[未注册用户]
黎波大哥,你好!
我有个问题想问你一下:我用vs2005向wince device部署的时候遇到这个错误:
错误4:这个产品的配置数据已损坏。请与技术支持人员联系。
原来是没有这个错误的,安装了wince 6.0后就出现了这个错误,修复安装了vs2005还是没有解决这个错误,不知道您有没有遇到过这种情况,或者有什么建议吗?谢谢!

  回复  引用  查看    
#12楼[楼主]2007-05-24 22:45 | Bob Li      
@zsz
不好意思,我没有安装过wince6,也没有遇到过这种问题。

  回复  引用    
#13楼2008-03-05 16:03 | 菜鸟一个[未注册用户]
黎波大哥你好,我需要把一个Hashtable的对象序列化,该如何使用CompactFormatter呢?例子里面是对自定义的类序列化的,那对这种已有的类怎么序列化啊?麻烦你了
  回复  引用  查看    
#14楼[楼主]2008-03-06 09:04 | 黎波      
@菜鸟一个
CompactFormatter 的单元测试中有序列化 Hashtable 的测试代码。
在“CompactFormatter-full-1.0.0.zip\CompactFormatter-1.0.0\src\Tests\HashtableTest.cs”

FileStream stream = new FileStream("Prova.bin",System.IO.FileMode.Create);
CompactFormatter CFormatter = new CompactFormatter();
CFormatter.AddSurrogate(typeof(Surrogate.DefaultSurrogates));

Hashtable s = new Hashtable();
s[1]=DateTime.Now;
s[2] = "Ciao Mondo";
s[3] = 3.1415;

CFormatter.Serialize(stream, s);
stream.Flush();
stream.Close();

stream = new FileStream("Prova.bin",System.IO.FileMode.Open);
CompactFormatter CFormatter2 = new CompactFormatter();
CFormatter2.AddSurrogate(typeof(Surrogate.DefaultSurrogates));
Hashtable temp = new Hashtable();

temp = (Hashtable)CFormatter2.Deserialize(stream);
stream.Close();

  回复  引用  查看    
#15楼[楼主]2008-03-06 09:11 | 黎波      
@黎波
这里还有一个CompactFormatter的改进版本,叫CompactFormatterPlus:
http://www.codeproject.com/KB/cs/CF_serializer.aspx" target="_new">http://www.codeproject.com/KB/cs/CF_serializer.aspx

  回复  引用    
#16楼2009-02-19 22:37 | craneshore
您好,遇到这个问题,在网上搜了好久直到看了这篇文章才解决,不过有个问题问下您,“重写 Equals 方法”这一步具体有什么作用,是不是必须具有的呢?
  回复  引用    
#17楼2009-04-01 21:24 | woodsonv[未注册用户]
CompactFormatter.dll是免费的吗?



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 720843




相关文章:

相关链接: