ProtoException当反序列化类成员打上AsReference去掉 [英] ProtoException when deserializing class with member marked with AsReference removed
问题描述
我得到一个 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 ofA
orB
are notAsReference = true
. A
andB
are not both set with aFoo
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屋!