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

问题描述 投票:1回答:1

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

在逻辑上,我想将继承性添加到生成的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

因此似乎不支持这种情况。现在还不清楚这是否适用于Base类或派生类中的IExtensible用法。基类必须保持可扩展性,因为我要应用多个扩展,但是扩展/派生类却不能。

我具有与下面从this post中获取的代码相似的代码。 现在在任何人将其标记为“重复”之前-并不是因为我的问题完全不同。当OP询问IExtensible的目的和不实施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);
}

问题:如何在上述情况下实现继承?我愿意修改派生类,您可以建议进行其他任何工作,甚至可以使用其他.NET Protobuf库。

c# inheritance protocol-buffers protobuf-net
1个回答
0
投票

这里的根本问题是发生碰撞:

  • protobuf-net通过将protobuf建模为多条消息(每种类型一个),并在每个决策点将其建模为oneof,从而在protobuf中实现继承(不具有继承)
  • 在protobuf中,每封邮件都可以带有扩展名
  • 但是现在,protobuf-net中扩展的实现是根据object
  • 因此尚不清楚您要将扩展程序应用于哪个message

我曾考虑过扩展API以使其对逻辑type(将映射到消息)进行跟踪,但这很复杂,需要我花费一些时间来添加。

[大多数其他protobuf工具完全不支持继承,因此我怀疑您会发现可行的解决方法。

所以:这就是为什么它不存在的原因;确实不是。给您一个解决方法,对不起。这里唯一的“修复”是“花时间实现每个类型的扩展存储和检索的复杂性”

© www.soinside.com 2019 - 2024. All rights reserved.