迁移到 MessagePack(二进制)

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

在从 BinaryFormatter 迁移的过程中,适用于 C# 的 MessagePack 的某些行为和功能将值得注意,尤其是在无法更改或需要尽量减少更改序列化类型的 API 时。

  • 默认情况下,仅公共类型是可序列化的。 仅当 StandardResolverAllowPrivate.Options 作为参数提供给 MessagePackSerializer.SerializeMessagePackSerializer.Deserialize 方法时,才能序列化私有结构和内部结构以及类。

  • MessagePack 要求使用 [MessagePackObject] 属性对每个可序列化类型进行批注。 可以使用 ContractlessStandardResolver 可以避免这种情况,但可能会导致将来版本控制出现问题。

  • 每个可序列化的非静态字段和属性都需要使用 [Key] 属性进行批注。 如果使用 [MessagePackObject(keyAsPropertyName: true)] 属性批注类型,则成员不需要显式批注。 在这种情况下,若要忽略某些公共成员,请使用 [IgnoreMember] 属性。

  • 若要序列化私有成员,请使用 StandardResolverAllowPrivate

  • 可以使用 System.Runtime.Serialization 批注代替 MessagePack 批注:使用 [DataContract] 代替 [MessagePackObject],使用 [DataMember] 代替 [Key],使用 [IgnoreDataMember] 代替 [IgnoreMember]。 如果要避免在定义可序列化类型的库中依赖 MessagePack,这些批注会非常有用。

  • 它支持只读/不可变类型和成员。 序列化程序将尝试使用与参数列表最匹配的公共构造函数。 可以使用 [SerializationConstructor] 属性以显式方式指定构造函数。

  • 通过易于创作的自定义格式化程序,可支持任意类型的 Serialization。 这消除了对属性和特定构造函数或成员模式的所有要求。

  • 序列化程序支持 .NET 基类库提供的最常用的内置类型和集合。 可以在官方文档中找到完整列表。它具有允许自定义的扩展点

警告

MessagePack 具有允许在不限制类型的情况下反序列化数据的 API。 根据 MessagePack 安全说明,应避免使用这些 API。

警告

某些 MessagePack API 的行为可通过可变静态进行自定义,这意味着代码可能会因为同一进程、AssemblyLoadContext 或 AppDomain 中其他代码可能会执行的操作而成功或失败。 还可以通过引用 MessagePackAnalyzer 包并启用 MsgPack001 和 MsgPack002 分析器,来保持代码的复原能力,这些分析器会指出任何使用具有可更改行为的 API 的情况。