• 【.net 深呼吸】序列化中的“引用保留”


    假设 K 类中有两个属性/字段的类型相同,并且它们引用的是同一个对象实例,在序列化的默认处理中,会为每个引用单独生成数据。

    看看下面两个类。

        [DataContract]
        public class 帅哥
        {
            [DataMember]
            public string Name { get; set; }
            [DataMember]
            public int Age { get; set; }
            [DataMember]
            public float Height { get; set; }
            [DataMember]
            public ContactInfo ContactData1 { get; set; }
            [DataMember]
            public ContactInfo ContactData2 { get; set; }
        }
    
        [DataContract]
        public class ContactInfo
        {
            [DataMember]
            public string Phone { get; set; }
            [DataMember]
            public string Email { get; set; }
        }

    假设 ContactInfo 表示联系方式,帅哥有两个联系方式。

    -------------------------------------------------------------

                ContactInfo cinfo = new ContactInfo
                {
                    Email = "big_pig@珊瑚虫.com",
                    Phone = "118116"
                };
    
                帅哥 wg = new 帅哥
                {
                    Name = "王小八",
                    Age = 99,
                    Height = 1.414f,
                    ContactData1 = cinfo,
                    ContactData2 = cinfo
                };

    在上面代码中,帅哥实例的两种联系方式都引用了同一个 ContactInfo 对象。如果把该帅哥实例序列化。

                DataContractSerializer szr = new DataContractSerializer(wg.GetType());
                MemoryStream mstream = new MemoryStream();
                szr.WriteObject(mstream, wg);

    就会得到以下XML文档:

    <帅哥 xmlns="http://schemas.datacontract.org/2004/07/SampleApp" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <Age>99</Age>
      <ContactData1>
        <Email>big_pig@珊瑚虫.com</Email>
        <Phone>118116</Phone>
      </ContactData1>
      <ContactData2>
        <Email>big_pig@珊瑚虫.com</Email>
        <Phone>118116</Phone>
      </ContactData2>
      <Height>1.414</Height>
      <Name>王小八</Name>
    </帅哥>

    从上面生成的XML文档可知,引用的尽管是同一个实例,但很显然,ContactInfo 的数据被写入了两次。

    ----------------------------------------------------------

    那么,如果改为保留引用呢,看

                DataContractSerializerSettings settings = new DataContractSerializerSettings();
                settings.PreserveObjectReferences = true;
                DataContractSerializer szr = new DataContractSerializer(wg.GetType(), settings);
                MemoryStream mstream = new MemoryStream();
                szr.WriteObject(mstream, wg);

    将 PreserveObjectReferences 属性设置为 true,表示同一实例引用只写入一次。

    修改后生成的XML文档如下:

    <帅哥 z:Id="1" xmlns="http://schemas.datacontract.org/2004/07/SampleApp" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
      <Age>99</Age>
      <ContactData1 z:Id="2">
        <Email z:Id="3">big_pig@珊瑚虫.com</Email>
        <Phone z:Id="4">118116</Phone>
      </ContactData1>
      <ContactData2 z:Ref="2" i:nil="true" />
      <Height>1.414</Height>
      <Name z:Id="5">王小八</Name>
    </帅哥>

    你看,这一回的 XML 是不是比刚才的要简短了?因为同一个 ContactInfo 实例只写入了一次,并且给其中一个引用分配一个 id,后面如果还用到,就直接使用对象的 id 就行了,这样避免了重复写入内容。

    好了,今天分享的内容不能称得上是高大上,但老周觉得,是有价值的,希望对各位有用。

  • 相关阅读:
    Unix压测工具学习
    C#获取北京时间
    MySql游标的使用以及5000万大表加索引
    【博客园客户端】博客园Android客户端更新:离线下载、本地收藏、RSS阅读
    Protobuf
    时间戳签名和或证书无法验证或已损坏(已解决)
    Vue插槽的理解和使用
    工作学习高效法则
    ES6 Promise用法小结
    绩效考核互评打分怎么操作?
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/6118728.html
Copyright © 2020-2023  润新知