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

本文关键字:Protobuf-net 异常 子类 未知 | 更新日期: 2023-09-27 18:06:54

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

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

然而,当从客户端发送对象到服务器或反之亦然时,我所知道的就是该对象将是'ReplicableObject'的某个子类。因此,我使用:

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

其中'ro'是ReplicableObject的子类。

然而,我得到了这个异常:

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

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

在这个例子中,我试图发送一个MessageObject

由于protobuf-net的文档很少,我被困在该怎么做上。我已经尝试了一些属性,但没有效果。

感谢您的帮助。

编辑:我应该说清楚,子类甚至可能不是我写的。

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

Protobuf是一种基于契约的序列化格式,设计为与平台无关。因此,没有类型的元数据包含在连接中,因为它不会应用于平台之间。甚至继承也不是核心protobuf规范的一部分。

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

如果您确实不能提前告诉实际类型,还有一个DynamicType选项,它将AssemblyQualifiedName写入流。如果你对这条路线感兴趣,那么请注意,该格式的"跨平台"特性开始崩溃,但它对. net -to-非常有用。净目的。

最简单的包装器,如:

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

包裹你的对象,它应该表现(至少在v2中;动态类型在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; }
    }
}