C#中复杂控件的序列化

来源:互联网 发布:钉钉绑定阿里云邮箱 编辑:程序博客网 时间:2024/05/22 14:21

    由于开发一个进销存系统的需要,近期对自己2004年写的报表控件的序列化过程进行了改造。

    原来的序列化使用了微软自带的序列化对象,用的是Binary方式。 使用过程中发现,只要版本稍有变动,控件就无法再支持原来的序列化文件了。 一直想对这个过程进行一些改造,却苦于没有时间。

    我的控件中,序列化对象是个单独的对象,设计时对数据进行了抽象,序列化不作为控件的整体,而是作为控件中的一个变量存在着,这样的好处是,只要在适当的时间改变一下这个对象,控件的内容就会随着这个对象发生变化。

    对象的名称叫SerialObject,实现ISerial接口。 原来的代码还在,仍然支持序列化方法。要下有大约17个数据对象,两个简单对象,表格的行数和列数。其它的都是复杂对象。

    因为XML对象本身有层次结构,这类似于对象的序列化。

    控件本身有N个接口实现,他们分别是:单元数据(用于保存单元格的内容),前景色,背景色,线型列表,线型,字体列表,字体,对齐方式,合并单元格,只读属性,打印属性,行对象,列对象,锁定对象,滚动条属性,左上列标等等。这里边的每个接口,都又是一个复杂的结构,有些使用了稀疏数组,有些组合了Dictionary,有些使用的ArrayList,有些存着范围,象颜色这个结构,存的是整型值(因为颜色本来就是个数值)。

    SerialObject设计了一个公共方法,以利于从外部调用: bool ToXML(XMLDocument doc);方法中分别生成以上方法的节点.  实现时的函数名称:doc.DocumentElement.AppendChild(XmlNode node); 这是xmldoc的顶级节点,反序列化时,只要把元素循环读取,就可以得到每一个对象。

    对象本身又是一个复合对象,用这个方法即可实现,                XmlNode node = null;
  node.AppendChild();  非顶级对象中,每个对象加入一个方法:ToXML(XMLNode node); 自顶向下地序列化时,只需要调用 顶级的XML,以下逐级便可以完成序列化。

    在序列化时object类型的处理:

    序列化的过程中,还有一个挑战,那就是,我设计了一个万能的接口,这个接口用于保存表示范围的数据,比如,象前景色,用户有时可能会设置某一列为某种颜色 ,这里,按一个一个单元格来保存,对于空间会有极大的浪费,这里,就会保存为一个范围,比如:只记下(1列,2行,2列,30行),极限情况下,存储空间能相差几百倍。即然是万能的,它能保存的对象当然是Object类型,序列化时,如果按同一个模式来保存,当然可以,麻烦就麻烦在反序列化时,如何得到对象。 比如:颜色保存为int开,只读表示为bool型 ,反序列化时,并不知道需要生成的对象是什么类型,因为序列化时没有保存类型 。bool型还好办,同样的1234567呢?  字符,日期,颜色,数量?当初从设计到实现,几乎用了两周的时间,对这一块动大手术,显然太浪费时间,为什么要动大手术呢?
     反序列化时无法得到类型,那只有在序列化时加入类型了,obj.GetType(),就可以返回类型 。 类型加入到Node的属性中,这个属性的名称我把它命名为 type, node.Attributes.Append("Type"); type的值,就是obj.GetType().ToString()的数据。

     反序列化的过程是序列化的逆过程,每个控件中加入FromXML(XMLNOde node)方法,从层调用即可很容易实现。

     从开始设计修改到修改,测试完成,共用了两个工作日完成。控件至今工作状态正常。

     这个设计过程中,很重要的一点是需要了解序列化的层次结构,每个对象只处理自己的事情,其它的交给上级对象或下级对象来处理。 对XML的使用,是一步一步查帮助文档完成的。

 

      这个思想,可以扩展使用到非XML文档的序列化。

 

     <这个思路的实现,在我的资源中可以全部下载到源代码>