.Net中的序列化方法

.Net中的序列化方法有三种:XML 序列化、SOAP 序列化和二进制序列化。若是序列化到文件的话,前两者生成的是 XML 文件,二进制序列化生成二进制文件。     跟序列化相关的两个类型:     SerializableAttribute:指示一个类是可以序列化的。     ISerializable:使对象可以自己控制其序列化和反序列化的过程。

    列表比较三种序列化方法。

 XMLSOAP 二进制
序列化器类XmlSerializer SoapFormatterBinaryFormatter
SerializableAttribute  标记不需要 需要
ISerializable 接口不需要实现,实现了也不起作用。可以不实现,但实现了就起作用。
无参构造函数必须有,系统提供的缺省无参构造函数也算。不需要,因为反序列化时不调用构造函数。
被序列化的数据成员公共属性和字段所有
产生文件大小
    XML序列化的优点是使用简单,也颇具灵活性,比如可以控制数据在 XML 文件中是作为 Element 还是作为 Attribute ,以及显示的名称等。XML 序列化对一般的应用是足以应付的,但当 序列化循环引用的对象,即有多个引用指向同一个对象实体时,XML 序列化机制将在每个引用的地方都创建一个对象副本。这除了会导致数据存储上的冗余外,更严重的是使一个对象在反序列化后变成了毫无关系的多个对象,即 XML 反序列化后可能得到错误的对象关系图表。比如下图所示的简单例子:    

对应三种类型分别有三个对象 cObject 及其成员 _aObject、 _bObject,_aObject 由 cObject 构造,_bObject 中存的是对 _aObject 的引用,即 cObject 的成员 _aObject 和 _bObject 的成员 _aObject 是同一个东西。则 ClassC 类型的对象 cObject 经 XML 序列化的结果是:

 

<ClassC xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 

  <Name>ccc</Name> 

  <AObject> 

    <ID>37</ID> 

    <Name>aaa</Name> 

  </AObject> 

  <BObject> 

    <Name>bbb</Name> 

    <AObject> 

      <ID>37</ID> 

      <Name>aaa</Name> 

    </AObject> 

  </BObject> 

</ClassC> 

 

 

从这个结果反序列化后得到的新的 cObject,其成员 _aObject 跟 _bObject 中的 _aObject 可就是两个对象了。要解决这个问题,我能想到的就是给对象加上 GUID 属性,在反序列化后根据 GUID 属性重新设置引用,不知还有没有其它办法。         SOAP 和二进制序列化的优点是可以精确地控制序列化及反序列化的过程,并可以序列化对象的非公共成员。所以对复杂对象的序列化,我们应该在实现 ISerializable 接口后,用 SOAP 或 二进制的方式保存数据。至于缺点,如果你嫌在类名上加个 Serializable 标记很麻烦的话,这也许算个缺点。     还是上面的例子,如果用 SOAP 序列化 cObject 对象,结果是:

 

<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 

    <SOAP-ENV:Body> 

        <a1:ClassC id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/SerializeTest.CrossReference/SerializeTest%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"> 

            <ClassCNameName id="ref-3">ccc</ClassCNameName> 

            <ClassCAObjectAObject href="#ref-4"/> 

            <ClassCBObjectBObject href="#ref-5"/> 

        </a1:ClassC> 

        <a1:ClassA id="ref-4" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/SerializeTest.CrossReference/SerializeTest%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"> 

            <ClassANameName id="ref-6">aaa</ClassANameName> 

            <ClassAIDID>37</ClassAIDID> 

        </a1:ClassA> 

        <a1:ClassB id="ref-5" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/SerializeTest.CrossReference/SerializeTest%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"> 

            <ClassBNameName id="ref-7">bbb</ClassBNameName> 

            <ClassBAObjectAObject href="#ref-4"/> 

        </a1:ClassB> 

    </SOAP-ENV:Body> 

</SOAP-ENV:Envelope> 

 

很明显,里面存的是对象引用,这是一个精确副本,反序列化后毫无问题。

附:ClassC 的一段代码:

 

public ClassC()

        {

            _name = "Unknown ClassC Object";

            InitData();

        }



        private void InitData()

        {

            _aObject = new ClassA( 1 );

            _aObject.Name = "aaa";

            _aObject.ID = 37;



            _bObject = new ClassB();

            _bObject.Name = "bbb";

            _bObject.AObject = _aObject;

        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值