带有未知子类的 Protobuf-net 异常

Posted

技术标签:

【中文标题】带有未知子类的 Protobuf-net 异常【英文标题】:Protobuf-net Exception with Unknown Subclasses 【发布时间】:2011-08-27 23:50:42 【问题描述】:

我开发了一个应用程序,旨在使用序列化对象将数据从客户端发送到服务器并返回等。

对于这个应用程序,我认为 protobuf-net 将是一个不错的选择(尤其是因为它可以很好地处理可变长度对象)。

但是,当从客户端向服务器发送对象或反之亦然时,我只知道该对象将是“ReplicableObject”的某个子类。因此,我正在使用:

Serializer.SerializeWithLengthPrefix(stream, ro, PrefixStyle.Base128);

其中 'ro' 是从 ReplicableObject 子类化的类型的对象。

但是,我得到了这个例外:

“ProtoBuf.ProtoException”类型的未处理异常发生在 protobuf-net.dll

附加信息:序列化过程中发现意外类型; 类型必须包含在 ProtoIncludeAttribute 中;找到 MessageObject 作为 ReplicableObject 传递

在这个特定的实例中,我正在尝试发送一个 MessageObject

由于 protobuf-net 的文档很少,所以我不知道该怎么做。我在这里和那里尝试了一些属性,但无济于事。

任何帮助表示赞赏。

编辑:我应该明确指出,子类甚至可能不是我写的。

【问题讨论】:

我刚从几天外回来。我稍后会看这个 【参考方案1】:

Protobuf 是一种基于契约的序列化格式,旨在独立于平台。因此,no 类型的元数据包含在线路上,因为它不适用于平台之间。甚至继承也不是核心 protobuf 规范的一部分。

protobuf-net 作为一个特定的实现引入了对继承的支持(通过一些烟雾和镜子),但理想情况下它应该仍然可以提前定义预期的类型 - 与其他序列化程序完全相同例如XmlSerializerDataContractSerializer。这可以通过使用[ProtoInclude(...)] 来指定预期的具体类型来完成。

如果您真的无法提前知道实际类型,还有一个DynamicType 选项,它将AssemblyQualifiedName 写入流中。如果您对这条路线感兴趣,请注意该格式的“跨平台”功能开始失效,但它对于 .NET 到 .NET 的目的非常有用。

最简单的包装器,例如:

[ProtoContract]
public class SomeWrapper 
     [ProtoMember(1, DynamicType = true)]
     public object Value get;set;

将您的对象包装在 that 中,它应该可以正常工作(至少在 v2 中;DynamicType 在 v1 中不存在)。完整示例:

[TestFixture]
public class SO7218127

    [Test]
    public void Test()
    
        var orig = new SomeWrapper Value = new SubType  Foo = 123, Bar = "abc";
        var clone = Serializer.DeepClone(orig);
        Assert.AreEqual(123, orig.Value.Foo);
        Assert.AreEqual("abc", ((SubType) clone.Value).Bar);
    
    [ProtoContract]
    public class SomeWrapper
    
        [ProtoMember(1, DynamicType = true)]
        public BaseType Value  get; set; 
    
    [ProtoContract]
    public class BaseType
    
        [ProtoMember(1)]
        public int Foo  get; set; 
    
    [ProtoContract]
    public class SubType : BaseType
    
        [ProtoMember(2)]
        public string Bar  get; set; 
    

【讨论】:

以上是关于带有未知子类的 Protobuf-net 异常的主要内容,如果未能解决你的问题,请参考以下文章

带有枚举的 Protobuf-net 反序列化异常

使用带有 protobuf-net 异常的代理对 List<T> 进行序列化

使用 Protobuf-Net 序列化未知子类型

使用知道架构的 protobuf-net 反序列化未知对象

ProtoBuf-Net ProtoInclude 泛型类型子类

限制 protobuf-net 继承“树”