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

时间:2011-08-27 23:50:42

标签: c# exception protobuf-net

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

对于这个应用程序,我认为protobuf-net是一个不错的选择(特别是当它处理可变长度的对象时)。

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

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

其中'ro'是从ReplicableObject继承的类型的对象。

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

  

发生了'ProtoBuf.ProtoException'类型的未处理异常   protobuf的-net.dll

     

其他信息:序列化期间发现意外类型;   ProtoIncludeAttribute必须包含类型;找到了MessageObject   作为ReplicableObject传递

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

由于protobuf-net的文档很少,我不知所措。我在这里尝试了一些属性但无济于事。

任何帮助表示感谢。

编辑:我应该说明子类可能不是我写的那些。

1 个答案:

答案 0 :(得分: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;}
}

将对象包装在并且它应该表现得很好(至少在v2中; v1中不存在DynamicType)。完整的例子:

[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; }
    }
}