【.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 就行了,这样避免了重复写入内容。
好了,今天分享的内容不能称得上是高大上,但老周觉得,是有价值的,希望对各位有用。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
2015-12-01 【非技术】谈谈简历那些事儿