获得“A引用跟踪对象改变反序列化过程参考”异常 [英] Getting 'A reference-tracked object changed reference during deserialization' exception

查看:185
本文介绍了获得“A引用跟踪对象改变反序列化过程参考”异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题涉及到这一块:<一href="http://stackoverflow.com/questions/7906356/how-to-solve-a-a-reference-tracked-object-changed-reference-during-deserializat">How解决&QUOT; A参考跟踪的对象序列化和QUOT过程中更改了参考;异常ProtoBuf.NET

由于上面的帖子已经关闭,我创建了一个新的,包括测试code来重现问题和异常堆栈跟踪。

这是怎么回事这里,为什么出错?另外,我不太清楚。对于ProtoInclude标签。如果标记等于ProtoMember然后我得到了重复场数的例外。所以,我通常将其设置为最大(ProtoMember标签)+ 1,这是该工具需要什么?

我运行这个例子从SVN(今下载)。

最新code

感谢

  [ProtoContract]
[ProtoInclude(6的typeof(B))]
大众A级
{
  [ProtoMember(1)]
  公众诠释Property1 {获得;组; }

  [ProtoMember(2)]
  公众诠释? Property2 {获得;组; }

  [ProtoMember(3)]
  公众诠释Property3 {获得;组; }

  [ProtoMember(4 DynamicType =真)
  公共对象Property4 {获得;组; }

  [ProtoMember(5,DynamicType =真)
  公共对象Property5 {获得;组; }

  公众覆盖布尔等于(obj对象)
  {
    A中的= OBJ为A;
    若(a == NULL)
      返回false;

    返回a.Property1 == this.Property1
           &功放;&安培; a.Property2 == this.Property2
           &功放;&安培; a.Property3 == this.Property3
           &功放;&安培;的Object.Equals(a.Property4,this.Property4)
           &功放;&安培;的Object.Equals(a.Property5,this.Property5);
  }
}

公共类B:
{
  [ProtoMember(1)]
  公共字符串Property6 {获得;组; }

  公众覆盖布尔等于(obj对象)
  {
    B B = OBJ为B;
    如果(二== NULL)
      返回false;

    返回b.Property6 == this.Property6和放大器;&安培; base.Equals(OBJ);
  }
}

[测试]
公共无效TestProtoBuf2()
{
  IList的&LT; A&GT;名单=新的名单,其中,A&GT;
                    {
                      新A {Property1 = 1,Property2 = 1,Property3 = 200,Property4 =测试1,Property5 = DateTime.Now},
                      新B {Property1 = 2,Property2 = 2,Property3 = 400,Property4 =的Test2,Property5 = DateTime.Now,Property6 =YYYY},
                      新A {Property1 = 3,Property2 = 3,Property3 = 600,Property4 =Test3的,Property5 =新的十进制数(200)},
                    };
  使用(var文件=新的FileStream(list.bin,FileMode.Create))
  {
    Serializer.Serialize(文件清单);
  }

  IList的&LT; A&GT; list2中;
  使用(var文件= File.OpenRead(list.bin))
  {
    list2中= Serializer.Deserialize&LT; IList的&LT; A&GT;&GT;(文件);
  }

  Assert.AreEqual(list.Count,list2.Count);

  的for(int i = 0; I&LT; list.Count;我++)
  {
    Assert.AreEqual(名单[I],list2中[I]);
  }
}
 

堆栈跟踪:

 在ProtoBuf.BclHelpers.ReadNetObject(对象的值,ProtoReader源的Int32键,输入型,NetObjectOptions选项)在BclHelpers.cs:行444
在ProtoBuf.Serializers.NetObjectSerializer.Read(对象的值,ProtoReader源)在C:\开发\ DOTNET \ protobuf网\ protobuf网\串行器\ NetObjectSerializer.cs:行37
在ProtoBuf.Serializers.TagDecorator.Read(对象的值,ProtoReader源)在C:\开发\ DOTNET \ protobuf网\ protobuf网\串行器\ TagDecorator.cs:行61
在ProtoBuf.Serializers.PropertyDecorator.Read(对象的值,ProtoReader源)在C:\开发\ DOTNET \ protobuf网\ protobuf网\串行器\ PropertyDecorator.cs:行53
在ProtoBuf.Serializers.TypeSerializer.Read(对象的值,ProtoReader源)在TypeSerializer.cs:行200
在ProtoBuf.Meta.RuntimeTypeModel.Deserialize(的Int32键,对象的值,ProtoReader源)在C:\开发\ DOTNET \ protobuf网\ protobuf网\元\ RuntimeTypeModel.cs:行418
在ProtoBuf.Meta.TypeModel.TryDeserializeAuxiliaryType(ProtoReader读者,DATAFORMAT格式的Int32标记,类型类型,参考对象的值,布尔skipOtherFields,布尔asListItem,布尔自动创建,布尔insideList)在C:\开发\ DOTNET \ protobuf网\ protobuf的-net \元\ TypeModel.cs:行895
在ProtoBuf.Meta.TypeModel.TryDeserializeList(ProtoReader读者,DATAFORMAT格式的Int32标记,类型listType,类型ITEMTYPE,参考对象的值)在C:\开发\ DOTNET \ protobuf网\ protobuf网\元\ TypeModel.cs:线712
在ProtoBuf.Meta.TypeModel.TryDeserializeAuxiliaryType(ProtoReader读者,DATAFORMAT格式的Int32标记,类型类型,参考对象的值,布尔skipOtherFields,布尔asListItem,布尔自动创建,布尔insideList)在C:\开发\ DOTNET \ protobuf网\ protobuf的-net \元\ TypeModel.cs:行851
在ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader阅读器,型号类型,对象的值,布尔noAutoCreate)在C:\开发\ DOTNET \ protobuf网\ protobuf网\元\ TypeModel.cs:行594
在ProtoBuf.Meta.TypeModel.Deserialize(流源,对象的值,类型类型,SerializationContext上下文)在C:\开发\ DOTNET \ protobuf网\ protobuf网\元\ TypeModel.cs:行518
在ProtoBuf.Meta.TypeModel.Deserialize(流源,对象的值,类型型)在C:\开发\ DOTNET \ protobuf网\ protobuf网\元\ TypeModel.cs:行500
在ProtoBuf.Serializer.Deserialize(流来源)在C:\开发\ DOTNET \ protobuf网\ protobuf网\ Serializer.cs:行69
 

解决方案

重新场数;他们需要在一个独特的类型;它不所需的,这是最大+1 - 它们不必是连续的 - 然而,小数字是preferable(只要它们是正的),如varint 编码可以打包低场数字(头)更有效。

重新参考跟踪问题;这是一个错误,并固定在当前Trunk - 感谢;的边缘的情况下,但固定的。

This question is related to this one: How to solve a "A reference-tracked object changed reference during deserialization" exception in ProtoBuf.NET

Since the above post has been closed, I created a new one that includes the test code to reproduce the problem and the exception stack trace.

What is going here, why the error? Also I am not clear on the tag for the ProtoInclude. If the tag is equal to a ProtoMember then I get an exception about a duplicate field number. So, I usually set it to max(ProtoMember tag) + 1. Is this what the tool expects?

I run this example with the latest code from svn (downloaded today).

Thanks

[ProtoContract]
[ProtoInclude(6, typeof(B))]
public class A
{
  [ProtoMember(1)]
  public int Property1 { get; set; }

  [ProtoMember(2)]
  public int? Property2 { get; set; }

  [ProtoMember(3)]
  public int Property3 { get; set; }

  [ProtoMember(4, DynamicType = true)]
  public object Property4 { get; set; }

  [ProtoMember(5, DynamicType = true)]
  public object Property5 { get; set; }

  public override bool Equals(object obj)
  {
    A a = obj as A;
    if (a == null)
      return false;

    return a.Property1 == this.Property1
           && a.Property2 == this.Property2
           && a.Property3 == this.Property3
           && Object.Equals(a.Property4, this.Property4)
           && Object.Equals(a.Property5, this.Property5);
  }
}

public class B: A
{
  [ProtoMember(1)]
  public string Property6 { get; set; }

  public override bool Equals(object obj)
  {
    B b = obj as B;
    if (b == null)
      return false;

    return b.Property6 == this.Property6 && base.Equals(obj);
  }
}

[Test]
public void TestProtoBuf2()
{
  IList<A> list = new List<A>
                    {
                      new A {Property1 = 1, Property2 = 1, Property3 = 200, Property4 = "Test1", Property5 = DateTime.Now},
                      new B {Property1 = 2, Property2 = 2, Property3 = 400, Property4 = "Test2", Property5 = DateTime.Now, Property6 = "yyyy"},
                      new A {Property1 = 3, Property2 = 3, Property3 = 600, Property4 = "Test3", Property5 = new Decimal(200)},
                    };
  using (var file = new FileStream("list.bin", FileMode.Create))
  {
    Serializer.Serialize(file, list);
  }

  IList<A> list2;
  using (var file = File.OpenRead("list.bin"))
  {
    list2 = Serializer.Deserialize<IList<A>>(file);
  }

  Assert.AreEqual(list.Count, list2.Count);

  for (int i = 0; i < list.Count; i++)
  {
    Assert.AreEqual(list[i], list2[i]);
  }
}

Stack trace:

at ProtoBuf.BclHelpers.ReadNetObject(Object value, ProtoReader source, Int32 key, Type type, NetObjectOptions options) in BclHelpers.cs: line 444
at ProtoBuf.Serializers.NetObjectSerializer.Read(Object value, ProtoReader source) in C:\Development\dotnet\protobuf-net\protobuf-net\Serializers\NetObjectSerializer.cs: line 37
at ProtoBuf.Serializers.TagDecorator.Read(Object value, ProtoReader source) in C:\Development\dotnet\protobuf-net\protobuf-net\Serializers\TagDecorator.cs: line 61
at ProtoBuf.Serializers.PropertyDecorator.Read(Object value, ProtoReader source) in C:\Development\dotnet\protobuf-net\protobuf-net\Serializers\PropertyDecorator.cs: line 53
at ProtoBuf.Serializers.TypeSerializer.Read(Object value, ProtoReader source) in TypeSerializer.cs: line 200
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize(Int32 key, Object value, ProtoReader source) in C:\Development\dotnet\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs: line 418
at ProtoBuf.Meta.TypeModel.TryDeserializeAuxiliaryType(ProtoReader reader, DataFormat format, Int32 tag, Type type, ref Object value, Boolean skipOtherFields, Boolean asListItem, Boolean autoCreate, Boolean insideList) in C:\Development\dotnet\protobuf-net\protobuf-net\Meta\TypeModel.cs: line 895
at ProtoBuf.Meta.TypeModel.TryDeserializeList(ProtoReader reader, DataFormat format, Int32 tag, Type listType, Type itemType, ref Object value) in C:\Development\dotnet\protobuf-net\protobuf-net\Meta\TypeModel.cs: line 712
at ProtoBuf.Meta.TypeModel.TryDeserializeAuxiliaryType(ProtoReader reader, DataFormat format, Int32 tag, Type type, ref Object value, Boolean skipOtherFields, Boolean asListItem, Boolean autoCreate, Boolean insideList) in C:\Development\dotnet\protobuf-net\protobuf-net\Meta\TypeModel.cs: line 851
at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in C:\Development\dotnet\protobuf-net\protobuf-net\Meta\TypeModel.cs: line 594
at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in C:\Development\dotnet\protobuf-net\protobuf-net\Meta\TypeModel.cs: line 518
at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type) in C:\Development\dotnet\protobuf-net\protobuf-net\Meta\TypeModel.cs: line 500
at ProtoBuf.Serializer.Deserialize(Stream source) in C:\Development\dotnet\protobuf-net\protobuf-net\Serializer.cs: line 69

解决方案

Re the field number; they need to be unique within a single type; it is not required that it is "max + 1" - they don't have to be contiguous - however, small numbers are preferable (as long as they are positive), as "varint" encoding can pack low field numbers (for headers) more efficiently.

Re the reference-tracking issue; this is a bug and is fixed in the current trunk - thanks; an edge case, but fixed.

这篇关于获得“A引用跟踪对象改变反序列化过程参考”异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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