ProtoException当反序列化类成员打上AsReference去掉 [英] ProtoException when deserializing class with member marked with AsReference removed

查看:546
本文介绍了ProtoException当反序列化类成员打上AsReference去掉的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到一个 ProtoException

  ProtoBuf.ProtoException:内部错误;发生的关键不匹配
 

与下面的code:

  [ProtoContract]
类Foo {}

类MemberRemovedTest
{
    [ProtoContract]
    类V1
    {
        [ProtoMember(1,AsReference =真)
        公共foo的{获得;组; }

        [ProtoMember(2,AsReference =真)
        公共富B {获得;组; }
    }

    [ProtoContract]
    类V2
    {
        [ProtoMember(2,AsReference =真)
        公共富B {获得;组; }
    }

    公共无效基本试验()
    {
        VAR V1 =新V1();
        v1.A =新的Foo();
        v1.B =新的Foo();

        byte []的缓冲区;
        V2 V2;
        使用(VAR流=新的MemoryStream())
        {
            Serializer.Serialize(流A);
            缓冲= stream.ToArray();
        }
        使用(VAR流=新的MemoryStream(缓冲))
        {
            V2 = Serializer.Deserialize< V2>(流);这里//异常
        }
    }
}
 

它将不可以抛出一个异常:

  • 第二构件是一个除去。
  • ProtoMember A 属性或 B 是没有 AsReference = 真正的
  • A B 不同时设置了实例。

我说的protobuf的理解支持构件脱落,但是这似乎表明有在那里他们必须保持周围的情况。

这是在protobuf的错误或有关删除成员坏的假设?

调用堆栈异常:

 在ProtoBuf.NetObjectCache.SetKeyedObject(的Int32键,对象值)在C:\开发\ protobuf网\ protobuf网\ NetObjectCache.cs:行67
   在ProtoBuf.BclHelpers.ReadNetObject(对象的值,ProtoReader源的Int32键,输入型,NetObjectOptions选项)在C:\开发\ protobuf网\ protobuf网\ BclHelpers.cs:行425
   在proto_6(对象,ProtoReader)
   在ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(对象的值,ProtoReader源)在C:\开发\ protobuf网\ protobuf网\串行器\ CompiledSerializer.cs:行57
   在ProtoBuf.Meta.RuntimeTypeModel.Deserialize(的Int32键,对象的值,ProtoReader源)在C:\开发\ protobuf网\ protobuf网\元\ RuntimeTypeModel.cs:行715
   在ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader阅读器,型号类型,对象的值,布尔noAutoCreate)在C:\开发\ protobuf网\ protobuf网\元\ TypeModel.cs:行679
   在ProtoBuf.Meta.TypeModel.Deserialize(流源,对象的值,类型类型,SerializationContext上下文)在C:\开发\ protobuf网\ protobuf网\元\ TypeModel.cs:行580
   在ProtoBuf.Serializer.Deserialize(流来源)在C:\开发\ protobuf网\ protobuf网\ Serializer.cs:行77
   在#### ProtoBuf.MemberRemovedTest.BasicTest()在MemberRemovedTest.cs:行56
 

解决方案

嗯....是的,有趣的。该死的。制定该方案的工作可能会非常困难;没有部件,我们没有足够的元数据来反序列化对象 - 或甚至只是知道它是可能被用作占位后来发生作为引用对象的对象。这将是不现实的存储的每个的跳过场进行处理以后 - 事实上,在非平凡的情况下,它是不可能的技术原因(如果作为参考是一个子对象,潜在地几被移除的成员级别的对象了,高了 - 我们无法处理,由于缺少元数据)

我没有更好的意见,现在不是是的,这是行不通的。让人头疼的 - 有趣的场景

I get a ProtoException

ProtoBuf.ProtoException : Internal error; a key mismatch occurred

with the following code:

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

It will not throw an exception if:

  • The second member is the one removed.
  • The ProtoMember attributes of A or B are not AsReference = true.
  • A and B are not both set with a Foo instance.

I am of the understanding that protobuf supports member removal, but this seems to indicate there are cases where they must be kept around.

Is this a bug in Protobuf or a bad assumption about removing members?

Call stack for exception:

   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

解决方案

Hmmm.... Yes, interesting. Damn. Making that scenario work could be extremely problematic; without the member, we don't have enough metadata to deserialize the object - or even just to know that it is an object that might be serving as a place-holder for an as-reference object that occurs later. It would be impractical to store every skipped field for processing later on - and indeed, in non-trivial cases it would be impossible for technical reasons (if the as-reference is a sub-object, potentially several levels down, of an object that is removed as a member higher up - we can't process that due to missing metadata).

I do not have a better comment right now than "yes, that won't work". Vexing - interesting scenario.

这篇关于ProtoException当反序列化类成员打上AsReference去掉的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆