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

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

看看下面两个类。code

    [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 表示联系方式,帅哥有两个联系方式。xml

 

-------------------------------------------------------------对象

            ContactInfo cinfo = new ContactInfo
            {
                Email = "big_pig@珊瑚虫.com",
                Phone = "118116"
            };

            帅哥 wg = new 帅哥
            {
                Name = "王小八",
                Age = 99,
                Height = 1.414f,
                ContactData1 = cinfo,
                ContactData2 = cinfo
            };

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

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

就会获得如下XML文档:ci

<帅哥 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 的数据被写入了两次。文档

----------------------------------------------------------get

那么,若是改成保留引用呢,看string

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

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

 

修改后生成的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 就好了,这样避免了重复写入内容。

 

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

相关文章
相关标签/搜索