反序列化带有标记为 AsReference 的成员的类时删除了 ProtoException

Posted

技术标签:

【中文标题】反序列化带有标记为 AsReference 的成员的类时删除了 ProtoException【英文标题】:ProtoException when deserializing class with member marked with AsReference removed 【发布时间】:2013-06-27 04:11:27 【问题描述】:

我得到一个 ProtoException

ProtoBuf.ProtoException : Internal error; a key mismatch occurred

使用以下代码:

[ProtoContract]
class Foo  

class MemberRemovedTest

    [ProtoContract]
    class V1
    
        [ProtoMember(1, AsReference = true)]
        public Foo A  get; set; 

        [ProtoMember(2, AsReference =  true)]
        public Foo B  get; set; 
    

    [ProtoContract]
    class V2
    
        [ProtoMember(2, AsReference = true)]
        public Foo B  get; set; 
    

    public void BasicTest()
    
        var v1 = new V1();
        v1.A = new Foo();
        v1.B = new Foo();

        byte[] buffer;
        V2 v2;
        using (var stream = new MemoryStream())
        
            Serializer.Serialize(stream, A);
            buffer = stream.ToArray();
        
        using (var stream = new MemoryStream(buffer))
        
            v2 = Serializer.Deserialize<V2>(stream); //Exception here
        
    

如果出现以下情况,它不会抛出异常:

第二个成员是删除的那个。 ABProtoMember 属性不是AsReference = trueAB 并非都使用 Foo 实例设置。

我了解到 protobuf 支持成员删除,但这似乎表明在某些情况下必须保留它们。

这是 Protobuf 中的错误还是删除成员的错误假设?

异常调用栈:

   at ProtoBuf.NetObjectCache.SetKeyedObject(Int32 key, Object value) in c:\Dev\protobuf-net\protobuf-net\NetObjectCache.cs: line 67
   at ProtoBuf.BclHelpers.ReadNetObject(Object value, ProtoReader source, Int32 key, Type type, NetObjectOptions options) in c:\Dev\protobuf-net\protobuf-net\BclHelpers.cs: line 425
   at proto_6(Object, ProtoReader)
   at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Serializers\CompiledSerializer.cs: line 57
   at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs: line 715
   at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs: line 679
   at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs: line 580
   at ProtoBuf.Serializer.Deserialize(Stream source) in c:\Dev\protobuf-net\protobuf-net\Serializer.cs: line 77
   at ####.ProtoBuf.MemberRemovedTest.BasicTest() in MemberRemovedTest.cs: line 56

【问题讨论】:

【参考方案1】:

嗯....是的,很有趣。该死。使这种情况发挥作用可能会带来极大的问题;如果没有该成员,我们就没有足够的元数据来反序列化该对象——或者甚至只是知道它是一个可能用作稍后出现的作为引用对象的占位符的对象。存储 每个 跳过的字段以供以后处理是不切实际的 - 事实上,在非平凡的情况下,由于技术原因是不可能的(如果 as-reference 是一个子对象,可能有几个级别下降,作为更高级别成员删除的对象 - 由于缺少元数据,我们无法处理)。

我现在没有比“是的,那行不通”更好的评论了。令人烦恼的 - 有趣的场景。

【讨论】:

谢谢,我们只需要保留一个空白字段。我们在您上面提到的非平凡案例中遇到了这个问题。如果您知道任何解决方法,他们将不胜感激,但现在听起来我们只需要添加一些 cmets :) @Landerah 听起来我也需要添加一些文档 cmets。

以上是关于反序列化带有标记为 AsReference 的成员的类时删除了 ProtoException的主要内容,如果未能解决你的问题,请参考以下文章

使用递归引用理解 ProtoBuf-Net AsReference

Java技术专题「性能优化系列」针对Java对象压缩及序列化技术的探索之路

C++ 模板工厂构造函数/反序列化

为 Jackson 自定义反序列化程序抛出带有 HTTP 状态代码的自定义异常

I/O(输入/输出)---序列化与反序列化

C# Json反序列化 数据协定类型 无法反序列化 由于未找到必需的数据成员