我想使用DataContractSerializer
,但我对其WriteObject
方法中的Stream
参数感到困惑——我发现我可以使用MemoryStream
或XmlWriter
。我想知道:
- 流选择对序列化有何影响?它会影响对象的大小吗
- 当使用
MemoryStream
时,我总是得到一个二进制对象吗
这些问题可能很基本,但我一直在谷歌上搜索,找不到明确的答案。谢谢
DataContractSerializer
本质上是一个基于xml的序列化程序。如果传递一个Stream
,它将构造一个封装流的XmlWriter
(特别是XmlDictionaryWriter
),然后核心序列化代码写入XmlWriter
。
流选择对序列化有何影响?它会影响对象的大小吗?
使用不同的Stream
实例不会影响内部发生的事情,但是与传递XmlWriter
相比,这里可能存在细微的差异,这取决于编码是什么。如果传递Stream
,则DataContractSerializer
使用UTF-8;但是如果你给它传递一个XmlWriter
,你可以指定不同的编码。
使用
MemoryStream
时,是否总是得到一个二进制对象?
MemoryStream
是byte[]
的包装器,是的:一旦你调用了.ToArray()
,你就只得到了二进制。然而,也是恰好是xml,这是二进制的。两者都可以。
如果您想要实际上是二进制的序列化(意思是:基本上是二进制序列化格式,而不是xml/json/csv/等),那么可以考虑像protobuf-net这样的东西。
正如Marc所说,如果您使用WriteObject
的重载,它占用Stream
,那么无论传入的Stream
实例的类型如何,DataContractSerializer
写入流的字节都将包括XML文档的UTF-8编码文本。如果实例是MemoryStream
,则最终会得到一个内存中的字节数组(因为MemoryStream就是这样),但这些字节包含UTF-8编码的XML文本,通常不会将其描述为二进制表示。
如果你使用WriteObject
的重载,它需要XmlWriter
,那么你最终得到的完全取决于你的XmlWriter
是什么类型,以及它是如何初始化的。就DataContractSerializer
而言,它将以适当的模式调用XmlWriter
的方法来描述表示对象状态的XMLInfoset。Infoset的编码方式取决于XmlWriter
的实现。
如果你有专门的需求,并且特别受虐,你可以实现自己的自定义XmlWriter
来进行任何类型的编码、压缩、加密,无论你喜欢什么。或者,您可以传递一个XmlTextWriter
,它将为您提供Infoset的文本编码(类似于Stream重载),但具有更多用于控制字符编码和文本格式的选项。通常情况下,你会传递一个XmlDictionaryWriter
,然后根据你创建它的方式,你有各种编码选项
这些选项包括WCF自己的XML Infosets二进制编码:以获得使用XmlDictionaryWriter.CreateBinaryWriter
创建实例的信息。由于WCF团队投入了大量精力来设计一个高效的二进制表示,以满足WCF的性能目标,我想,如果您能够确保生成的序列化对象只需要通过.NET代码进行反序列化,那么您将很难想出一个更好的选项。如果您需要基于公共标准的二进制表示,您可以考虑XmlDictionaryWriter
的MTOM
风格。