如何使用MessagePack序列化第三方库中无法标记特性的对象?
MessagePack-CSharp 序列化第三方无源码对象的替代方案
MessagePack-CSharp确实支持类似Protobuf代理(Surrogate)的实现,无需修改第三方类的源码,核心思路是通过**自定义格式化器(IMessagePackFormatter)**完成对象与代理类的转换映射。
实现步骤
- 定义代理类:创建与第三方类属性匹配的代理类,用于承载序列化/反序列化的数据:
public class Point3DSurrogate { public float X { get; set; } public float Y { get; set; } public float Z { get; set; } }
- 实现自定义格式化器:实现
IMessagePackFormatter<Point3D>接口,在序列化时将第三方对象转成代理对象,反序列化时再转换回第三方对象:
public class Point3DFormatter : IMessagePackFormatter<Point3D> { public void Serialize(ref MessagePackWriter writer, Point3D value, MessagePackSerializerOptions options) { var surrogate = new Point3DSurrogate { X = value.X, Y = value.Y, Z = value.Z }; options.Serializer.Serialize(ref writer, surrogate); } public Point3D Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { var surrogate = options.Serializer.Deserialize<Point3DSurrogate>(ref reader); return new Point3D(surrogate.X, surrogate.Y, surrogate.Z); } }
- 注册格式化器并使用:把自定义格式化器添加到序列化选项中,后续序列化/反序列化指定该选项即可:
// 配置序列化选项,注册自定义格式化器 var serializeOptions = MessagePackSerializerOptions.Standard .WithFormatter(new Point3DFormatter()); // 序列化第三方对象 var pp = new Point3D(0, 0, 0); byte[] bytes = MessagePackSerializer.Serialize(pp, serializeOptions); // 反序列化回第三方对象 var deserializedPoint = MessagePackSerializer.Deserialize<Point3D>(bytes, serializeOptions);
额外说明
如果需要批量处理多个第三方类型,也可以通过自定义ContractResolver扩展,但上述自定义格式化器的方式最贴近Protobuf中Surrogate的使用逻辑,直接针对目标类型做一对一的转换映射,逻辑清晰且易于维护。
内容的提问来源于stack exchange,提问作者niks
相关产品推荐
相关产品推荐

