选择序列化程序
尚不存在 BinaryFormatter 的直接替代产品,但有多种推荐用于序列化 .NET 类型的序列化程序。 无论选择哪个序列化程序,都需要更改原有解决方案才能集成新的序列化程序。 在相关迁移过程中,重要的是要考虑权衡以下两个方面:一是强制新的序列化程序通过尽可能少的更改来处理现有类型;二是对类型进行重构,以便使用所选的序列化程序进行符合习惯的 serialization。 选择序列化程序后,应详细查看其文档以了解最佳做法。
如果二进制 serialization 格式不是必需的,可以考虑使用 JSON 或 XML serialization 格式。 .NET 中包含了这些序列化程序,并提供对这些程序的正式支持。
- 使用 System.Text.Json的 JSON
- 使用
System.Runtime.Serialization.DataContractSerializer
的 XML
如果紧凑二进制表示形式对于你的方案很重要,建议使用以下 serialization 格式和开源序列化程序:
- 使用适用于 C# 的 MessagePack 的 MessagePack
- 使用 protobuf-net 的 协议缓冲区
是否能够控制对序列化的类型的 API 形状的更改会影响 serialization 的方向和方法。 如果能够使用新特性批注类型、添加新构造函数、使类型/成员公共化以及将字段更改为属性,则迁移到这些序列化程序可能是更直接的方法。 如果不具备这些能力,使用新式序列化程序可能需要实现自定义转换器或解析程序。
功能 | BinaryFormatter | System.Text.Json | DataContractSerializer | 适用于 C# 的 MessagePack | protobuf-net |
---|---|---|---|---|---|
Serialization 格式 | 二进制 (NRBF) | JSON | XML | 二进制 (MessagePack) | 二进制(协议缓冲区) |
紧凑表示形式 | ✔️ | ❌ | ❌ | ✔️ | ✔️ |
人工可读取 | ❌️ | ✔️ | ✔️ | ❌️ | ❌️ |
性能 | ❌️ | ✔️ | ❌ | ✔️ | ✔️ |
[Serializable] 特性支持 |
✔️ | ❌ | ✔️ | ❌ | ❌ |
公共类型序列化 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
非公共类型序列化 | ✔️ | ✔️ | ✔️ | ✔️(需要解析程序) | ✔️ |
字段序列化 | ✔️ | ✔️(选择加入) | ✔️ | ✔️(需要特性) | ✔️(需要特性) |
非公共字段序列化 | ✔️ | ✔️(需要解析程序) | ✔️ | ✔️(需要解析程序) | ✔️(需要特性) |
属性序列化 | ✔️* | ✔️ | ✔️ | ✔️(需要特性) | ✔️(需要特性) |
只读成员反序列化 | ✔️ | ✔️(需要特性) | ✔️ | ✔️ | ✔️(需要无参数构造函数) |
多态类型层次结构 | ✔️ | ✔️(需要特性) | ✔️ | ✔️(需要特性) | ✔️(需要特性) |
AOT 支持 | ❌️ | ✔️ | ❌ | ✔️ | ❌(已计划) |
使用 System.Text.Json 的 JSON
System.Text.Json
库是一种新式序列化程序,它强调 JavaScript 对象表示法 (JSON) 格式的安全性、高性能和低内存分配。 JSON 是人工可读的,具有广泛的跨平台支持。 虽然基于文本的格式不像二进制格式那么紧凑,但通过压缩可以显著减小其大小。
Serialization 不支持非公共成员和只读成员,除非通过特性和构造函数进行专门处理。 System.Text.Json 还支持自定义serialization序列化和反序列化,能更好地控制如何将类型转换为 JSON(反之亦然)。 System.Text.Json 不支持 [Serializable]
特性。
使用 DataContractSerializer 的 XML
DataContractSerializer 在 .NET Framework 3.0 中引入,用于序列化和反序列化 Windows Communication Foundation (WCF) 消息中发送的数据。 DataContractSerializer 是一种 XML 序列化程序,完全支持 BinaryFormatter
使用的 serialization 编程模型,这意味着它遵循 ISerializable 的 [Serializable]
特性和实现。 因此它是所需迁移工作量最少的序列化程序。 但是它需要预先指定已知类型(而大多数 .NET 集合和基元类型均包含在默认允许列表中,无需指定)。
虽然 DataContractSerializer
从 BinaryFormatter 迁移时具有前述功能优势,但它不像其他选择那样现代化或性能高。
迁移到 DataContractSerializer (XML)。
注意
不要将 DataContractSerializer 与 NetDataContractSerializer 混淆。 NetDataContractSerializer 也标识为危险的序列化程序。
使用 MessagePack 的二进制格式
MessagePack 是一种紧凑二进制 serialization 格式,与 JSON 和 XML 相比,生成的消息更小。 开放源代码适用于 C# 的 MessagePack 库性能非常高,提供内置的超快速 LZ4 压缩,可得到更小的数据。 该格式在使用 DataContractSerializer
或库自己的特性来批注数据类型时,效果最佳。 它经过配置后可支持 AOT 环境、非公共类型和成员以及只读类型和成员。
使用 protobuf-net 的二进制格式
protobuf-net 库是适用于 .NET 的基于协定的序列化程序,它使用二进制协议缓冲区serialization格式。 API 遵循典型的 .NET 模式,与 XmlSerializer
和 DataContractSerializer
大致相当。 此常用库功能丰富,可以处理非公共类型和字段,但许多方案需要将特性应用于成员。