Kevin Shan

统计

如何序列化Control等复杂类型对象

.NET Framework提供了将对象序列化和反序列化的能力。利用这种机制,我们可以将对象实例的状态存储到存储媒体上,也可以将对象从一个地方传递到另一个地方。

.NET Framework提供了一些用于序列化的类。一个是BinnaryFormatter,它使用二进制格式序列化对象。另一个是SoapFormatter,它使用soap格式(基于XML格式)序列化对象。还可以使用XMLSerializer将对象序列化成XML格式。然而这种序列化机制是有一定限制的,它只能序列化特定的对象。这些对象要么是从MarshalByRefObject派生的对象,要么是标记为Serializable的简单类型对象。像System.Windows.Forms.Control这类复杂的对象就不能被支持。

今天我要介绍的是如何序列化System.Windows.Forms.Control这类复杂的对象。在介绍之前,我们先看看序列化和反序列化的流程。

序列化反序列化流程图

 

分离出复杂的逻辑,最简单的逻辑只有两步,第一步-序列化过程:将内存中的对象数据用XML格式的数据表示。第二步-反序列化过程:构造一个新对象,并将XML格式表示的数据赋值给这个新的对象。这样,原始对象和新构造的对象会有同样的数据,即表示同一种状态。

经常使用VS2005,VS2008等IDE的开发人员,特别是做过Design Time开发的开发人员可能会注意到,这个过程其实和IDE自动生成控件代码的过程相似。

IDE设计编译流程

在使用IDE的过程中,我们在Design环境中给Form拖一个TextBox控件,IDE会在Design环境中创建一个TextBox控件,并生成相关C#或者VB等格式的代码。这个阶段叫设计时(DesignTime)。这个过程类似我们刚才讲到的第一步-序列化过程。而我们点击运行的时候,这些文本格式的代码又会被编译运行,根据编译的代码生成一个新TextBox控件在Form上显示。这个阶段叫运行时(RunTime)。这个过程就类似我们刚才讲到的第二步-反序列化过程。可以看出来,IDE在DesignTime下是将控件实例序化成C#或VB等代码。而在RunTime下是将代码编译运行,生成新的控件实例来保持DesignTime下设计的状态与RunTime下显示的状态一致。事实上,这也是序列化和反序列化的一种方式。

既然IDE的这个过程也是序列化和反序列化的方式,那么IDE是怎么实现复杂控件序列化和反序列化的呢?这可能需要另外一篇文章才能讲清楚,这里暂不研究。不过我们可以知道,IDE是有能力做这件事情的。我们也可以利用IDE的这种能力,来实现复杂控件的序列化和反序列化。

下面这段代码演示了如何利用IDE的这种能力序列化一个Object。

SaveObject

下面这段代码演示了如何利用IDE的这种能力反序列化一个Object。 

LoadObject

利用IDE的这种能力,我们还可以做很多事情,比如深度克隆控件。有时候,我们需要克隆一个复杂的控件,然而办法有限,要么使用反射枚举控件所有字段赋值,要么给所有属性一个一个赋值。而属性之间的依赖关系,引用类型的属性如何处理等都是难题。利用控件序列化和反序列化,可以轻松实现控件的克隆。再比如在RunTime下得到控件的C#,VB等代码,因为序列化的中间产物就是C#,VB等代码,所以利用这个机制很容易实现。这些代码我写了一个类库,需要的可以和我联系。代码太多,在这里就不贴了。

补充:现在我已经把源代码上传了。可以在这里下载

原创文章,转载请注明出处。KevinShan Email:txhak@163.com。

posted on 2008-05-27 17:03  Kevin Shan  阅读(...)  评论(...编辑  收藏