不支持 Protobuf-NET IExtensible 继承的解决方法

Workaround for Protobuf-NET IExtensible Inheritance Not Supported

我正在使用 Protobuf-NET 反序列化协议缓冲区数据,并且正在处理多个相同但扩展名略有不同的 Proto 文件。基本上每个 Proto 提要都是 99% 相同的,然后有 1 或 2 个彼此不同的字段作为每个字段的扩展提供。所以我最终得到了多个 99% 相同的 Proto classes。

从逻辑上讲,我想为生成的 C# 原型文件添加继承,以避免 99% 的冗余代码解析每个提要。问题是反序列化时出现以下错误:

System.NotSupportedException
  HResult=0x80131515
  Message=IExtensible is not supported in structs or classes with inheritance
  Source=protobuf-net
  StackTrace:
   at ProtoBuf.Serializers.TypeSerializer..ctor(TypeModel model, Type forType, Int32[] fieldNumbers, IProtoSerializer[] serializers, MethodInfo[] baseCtorCallbacks, Boolean isRootType, Boolean useConstructor, CallbackSet callbacks, Type constructType, MethodInfo factory) in C:\code\protobuf-net\src\protobuf-net\Serializers\TypeSerializer.cs:line 97
   at ProtoBuf.Meta.MetaType.BuildSerializer() in C:\code\protobuf-net\src\protobuf-net\Meta\MetaType.cs:line 480
   at ProtoBuf.Meta.MetaType.get_Serializer() in C:\code\protobuf-net\src\protobuf-net\Meta\MetaType.cs:line 372
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source) in C:\code\protobuf-net\src\protobuf-net\Meta\RuntimeTypeModel.cs:line 802
   at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in C:\code\protobuf-net\src\protobuf-net\Meta\TypeModel.cs:line 718
   at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in C:\code\protobuf-net\src\protobuf-net\Meta\TypeModel.cs:line 590
   at ProtoBuf.Serializer.Deserialize[T](Stream source) in C:\code\protobuf-net\src\protobuf-net\Serializer.cs:line 68

所以好像不支持这种场景。现在不清楚的是,这是否适用于基础 class 或派生 class 中的 IExtensible 用法。基础 class 必须保持可扩展性,因为我正在应用多个扩展,但扩展/派生 classes 不。

我有类似于下面摘自 this post 的代码。 现在在任何人将其标记为 "Duplicate" 之前 - 这不是因为我的问题完全不同。虽然 OP 在询问 IExtensible 的目的和不实施它的后果,但我在询问上述用例的任何可能的解决方法或解决方案。

[ProtoBuf.ProtoInclude(1000, typeof(DerivedClass))]
public partial class BaseClass : ProtoBuf.IExtensible 
{ 
    ... 
    private IExtension extensionObject;
    IExtension IExtensible.GetExtensionObject(bool createIfMissing)
    {
        return Extensible.GetExtensionObject(ref extensionObject, createIfMissing);        
    }
}    

public partial class DerivedClass : BaseClass, ProtoBuf.IExtensible
{
    ... 
    private IExtension extensionObject;
    IExtension IExtensible.GetExtensionObject(bool createIfMissing)
    {
        return Extensible.GetExtensionObject(ref extensionObject, createIfMissing);        
    }
}   

var baseObject = new MyClass { ... };    
DerivedClass derivedObject;
using (var stream = new MemoryStream())
{
    Serializer.Serialize(stream, baseObject);  // throws runtime exception
    stream.Seek(0, SeekOrigin.Begin);
    derivedObject = Serializer.Deserialize<DerivedClass>(stream);
}

问题:如何实现上述场景的继承?我愿意修改派生的 class,您可以建议任何其他解决方法,甚至使用另一个 .NET Protobuf 库。

这里的根本问题是存在碰撞:

  • protobuf-net 通过将其建模为多条消息(每种类型一个)和每个决策点 oneof
  • 来实现 protobuf 中的继承(它没有继承)
  • 在 protobuf 中,每条消息都可以有扩展名
  • 但是现在,protobuf-net 中的扩展实现是每个 object
  • 所以不清楚您要对哪个消息应用扩展

我考虑过扩展 API 以使其根据逻辑 type(将映射到消息)跟踪扩展,但这很复杂并且我需要时间来补充。

大多数其他 protobuf 工具根本不支持继承,所以我怀疑您是否会找到可行的解决方法。

所以:这就是它不存在的原因; really.givr 这不是解决方法,抱歉。这里唯一的"fix"是"take the time to implement the complexity of per-type extension storage and retrieval"