如何为含object属性的ChangeRecord类编写自定义protobuf-net序列化器
问题
我正尝试编写一个自定义protobuf-net序列化器,用于将object类型的属性序列化到传输流中。现有代码如下:
[ProtoContract(Serializer=typeof(ChangeRecordSerializer))] public class ChangeRecord { public object NewValue {get;set;} }
目前我的实现进度如下:
public class ChangeRecordSerializer : ISerializer<ChangeRecord> { public void Write(ref ProtoWriter.State state, ChangeRecord value) { state.WriteString(1, value.NewValue.GetType().FullName; // how to serialize value.NewValue??? } public void Read(ref ProtoReader.State state, ChangeRecord value) { int num = 0; string typeName = null; while ((num = state.ReadFieldHeader()) > 0) { switch (num) { case 1: typeName = state.ReadString(); break; case 2: var type = Type.GetType(typeName); // how to read value.NewValue??? break; } } } public SerializerFeatures Features => SerializerFeatures.CategoryMessage | SerializerFeatures.WireTypeString; }
请问如何实现上述代码中两处注释标记的逻辑?
解决方案
1. 实现Write方法中的序列化逻辑
先修正原代码的语法错误(GetType().FullName后缺少右括号),然后借助protobuf-net内置的Serializer.NonGeneric.Serialize方法,将NewValue序列到字段2中:
public void Write(ref ProtoWriter.State state, ChangeRecord value) { // 写入类型全名到字段1 state.WriteString(1, value.NewValue.GetType().FullName); // 序列化NewValue到字段2 Serializer.NonGeneric.Serialize(ref state, 2, value.NewValue); }
注意:自定义类型必须添加[ProtoContract]和[ProtoMember]属性才能正常序列化;int、string等系统内置类型无需额外配置,protobuf-net会自动处理。
2. 实现Read方法中的反序列化逻辑
使用Serializer.NonGeneric.Deserialize方法,根据读取到的类型全名获取Type后,反序列化字段2的数据并赋值给NewValue,同时建议添加未知字段跳过逻辑增强鲁棒性:
public void Read(ref ProtoReader.State state, ChangeRecord value) { int num = 0; string typeName = null; while ((num = state.ReadFieldHeader()) > 0) { switch (num) { case 1: typeName = state.ReadString(); break; case 2: var type = Type.GetType(typeName); // 反序列化字段2的数据到NewValue value.NewValue = Serializer.NonGeneric.Deserialize(type, ref state); break; default: // 跳过未知字段,避免解析失败 state.SkipField(); break; } } }
额外提示:如果目标类型不在当前程序集或系统核心程序集中,建议用GetType().AssemblyQualifiedName替代FullName,确保Type.GetType能准确找到对应类型。
内容的提问来源于stack exchange,提问作者Wolfgang
相关产品推荐
相关产品推荐

