protobuf-net序列化实现接口的结构体报Unexpected sub-type错误
问题根因
这是protobuf-net的设计限制,不是配置错误。
- 当你以接口类型作为序列化根类型(即序列化时传入的声明类型为
Id接口)时,通过[ProtoInclude]特性注册子类型的逻辑,默认仅支持引用类型(class),会自动过滤掉所有值类型(struct)。 - 你定义的
StructId是结构体(值类型),哪怕加了[ProtoContract]、在接口上正确配置了[ProtoInclude(102, typeof(StructId))],序列化器初始化时也不会把它识别为Id接口的合法子类型,最终抛出Unexpected sub-type: StructId错误。 - 提前调用
Serializer.PrepareSerializer<Id>()无法解决问题,因为值类型子类型过滤是在序列化器初始化阶段就执行的,和延迟加载无关。
解决方案
你可以根据自己的业务场景选以下任意一种方案:
- 方案1:如果允许修改类型定义,直接把
StructId从结构体改为类,保留现有ProtoInclude配置即可正常完成多态序列化。 - 方案2:如果必须保留
StructId的结构体设计,就放弃接口多态序列化逻辑,序列化时直接指定序列化类型为具体结构体类型:
protobuf-net本身对结构体的序列化支持是完善的,只是不支持将结构体作为接口多态下的子类型通过特性配置识别。Serializer.Serialize<StructId>(stream, structIdInstance); - 方案3:如果既要保留
StructId的结构体定义,又要支持以Id接口为根的多态序列化,可以使用protobuf-net 3.x及以上版本,跳过特性配置,在程序启动时通过运行时API手动注册子类型:
这种方式可以绕过特性模式下的值类型子类型过滤逻辑。RuntimeTypeModel.Default[typeof(Id)] .AddSubType(102, typeof(StructId));
内容的提问来源于stack exchange,提问作者Yurii
相关产品推荐
相关产品推荐

