选择序列化程序

尚不存在 BinaryFormatter 的直接替代产品,但有多种推荐用于序列化 .NET 类型的序列化程序。 无论选择哪个序列化程序,都需要更改原有解决方案才能集成新的序列化程序。 在相关迁移过程中,重要的是要考虑权衡以下两个方面:一是强制新的序列化程序通过尽可能少的更改来处理现有类型;二是对类型进行重构,以便使用所选的序列化程序进行符合习惯的 serialization。 选择序列化程序后,应详细查看其文档以了解最佳做法。

如果二进制 serialization 格式不是必需的,可以考虑使用 JSON 或 XML serialization 格式。 .NET 中包含了这些序列化程序,并提供对这些程序的正式支持。

  1. 使用 System.Text.Json的 JSON
  2. 使用 System.Runtime.Serialization.DataContractSerializer 的 XML

如果紧凑二进制表示形式对于你的方案很重要,建议使用以下 serialization 格式和开源序列化程序:

  1. 使用适用于 C# 的 MessagePackMessagePack
  2. 使用 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] 特性。

迁移到 System.Text.Json (JSON)。

使用 DataContractSerializer 的 XML

DataContractSerializer 在 .NET Framework 3.0 中引入,用于序列化和反序列化 Windows Communication Foundation (WCF) 消息中发送的数据。 DataContractSerializer 是一种 XML 序列化程序,完全支持 BinaryFormatter 使用的 serialization 编程模型,这意味着它遵循 ISerializable[Serializable] 特性和实现。 因此它是所需迁移工作量最少的序列化程序。 但是它需要预先指定已知类型(而大多数 .NET 集合和基元类型均包含在默认允许列表中,无需指定)。

虽然 DataContractSerializer 从 BinaryFormatter 迁移时具有前述功能优势,但它不像其他选择那样现代化或性能高。

迁移到 DataContractSerializer (XML)。

使用 MessagePack 的二进制格式

MessagePack 是一种紧凑二进制 serialization 格式,与 JSON 和 XML 相比,生成的消息更小。 开放源代码适用于 C# 的 MessagePack 库性能非常高,提供内置的超快速 LZ4 压缩,可得到更小的数据。 该格式在使用 DataContractSerializer 或库自己的特性来批注数据类型时,效果最佳。 它经过配置后可支持 AOT 环境、非公共类型和成员以及只读类型和成员。

迁移到 MessagePack(二进制)

使用 protobuf-net 的二进制格式

protobuf-net 库是适用于 .NET 的基于协定的序列化程序,它使用二进制协议缓冲区serialization格式。 API 遵循典型的 .NET 模式,与 XmlSerializerDataContractSerializer 大致相当。 此常用库功能丰富,可以处理非公共类型和字段,但许多方案需要将特性应用于成员。

迁移到 protobuf-net(二进制)。