标签:
.NET提供了很多序列化对象的方法,了解他们之间的区别才能更好地确定使用哪一种序列化方式并正确地使用。本文从下面几个方面对标题中的三种序列化方法进行了分析。
先把结果整理出来再分析:代码可以从这里下载,所写测试可能并不全面,所以如果有什么错误,欢迎大家指出,不然要误人子弟了。不过有这篇更误人子弟的文章殿底(Google top 1),我相信这个表不会更糟。
XmlSerializer | DataContractSerializer | BinaryFormatter | |
范围 | Both | Both | Field Only |
可见性 | Public Only | All | All |
只读属性 | 不支持 | 支持,但要加Attribute | N/A |
回调支持 | 不支持 | 支持 | 支持 |
循环引用 | 不支持 | 支持,但要加Attribute | 支持 |
Dictionary | 不支持 | 支持,专有格式 | 支持 |
乱序读 | 支持 | 不支持 | 不支持 |
自定义格式 | 支持,要加Attribute | 不支持Xml Attribute | 通过接口 |
Attribute要求 | 不必要 | 不必要 | 必须有Serializable |
有几点需要解释一下。
在我写的几个测试用例中,无论对于简单对象,还是嵌套对象,还是数组重复引用对象,这几个Serializer的性能和大小基本在一个数量级上。他们之间功能上的差异远大于他们性能上的差异。这个时候,使用哪个方法的决策应该取决于功能及其约束,而不是性能。如果你在意性能,应该用第三方库,如Google的protobuf-net。无论从性能、序列化结果的大小还是兼容性上,protobuf-net比这三者都要优秀,当然,not human readable。
不少同类文章都声称XmlSerializer和DataContractSerializer都要求在类上加相应的Attribute。但事实上并不是这样。只有当你想要改变默认的序列化结果时,Attribute才是必要的。
最常见的一个错误就是,给XmlSerializer要用到的类加Serializable Attribute。这个Attribute其实是给BinaryFormatter和SoapFormatter用的,一般用在Remoting和Messaging上。
乱序读的意思是,Deserialize的过程中,不对Xml节点的顺序做要求。Xml本身就是一种标记性的,带有声明性的语言,多数基于Xml的网络协议都不会对Xml节点的顺序做要求。比如常见的RSS,ATOM,OPDS等。
WCF使用的DataContractSerializer要求Xml节点顺序要么严格指定,要么按字母顺序排列,或许有性能上考虑,但是WCF的定位才是允许DataContractSerializer严格要求Xml节点顺序的根本原因。WCF本身是用于通信的,其对序列化的定位,仅仅只是消息传递的手段,消息格式的严格定义并没有什么不好,而且调用方的代码都可以通过WSDL来生成,自然也就更不会出现解析时的问题。所以不支持乱序读完全是由其功能设定决定的。
XmlSerializer,在我看来可以做为Object Xml Mapping的工具,当然要尽可能支持所有Xml的标准。
XmlSerializer和DataContractSerializer都支持IXmlSerializer接口。通过这个接口DataContractSerializer甚至可以支持Attribute,但是,这其实已经不是在使用DataContractSerializer的序列化机制了。而且在实际项目中也不具备可操作性。所以在上表中,还是把DataContractSerializer标记为不支持Xml Attribute。
还有一些常见的接口,如ISerializable和IDeserializationCallback是给BinaryFormatter用的,以支持自定义序列化的过程。这里我很奇怪为了BinaryFormatter已经支持了OnDeserialized Attribute,为什么还有这么个接口来提供相似的功能。
两个Xml序列化方法还有一些小的挺有意思的差别,我试图猜测产生这种差异的原因,却没想出来,或许是一些微软员工不为人知的设计理念,也许只是写代码时的顺心而为罢了。
基于上面的客观结果,相信你已经有了自己的判断。我个人意见,DataContractSerializable就用在它应该用的地方吧,如果不是用WCF,还是不要用它了,它的序列化结果有一些微软专属的东西。对于来自网络的松散Xml接口数据,XmlSerializer是不二之选。如果想把对象完整地保存下来(数据与状态),同时又不需要被人看。那就用BinaryFormatter吧。如果对性能或是数据大小要求比较高,那这三个就都能用,用protobuff吧。
这些信息算是一种经验,但是绝对不适合作面试或是笔试题用。
XmlSerializer, DataContractSerializer 和 BinaryFormatter区别与用法分析
标签:
原文地址:http://www.cnblogs.com/shouce/p/5551760.html