Protobuf-net根级列表序列化AsReference

时间:2013-04-29 16:55:43

标签: serialization reference protobuf-net

我正在尝试使用protobuf-net库序列化一组对象。我遇到的问题是集合中的顶级对象没有被设置为图形中的引用,因此当它们在序列化子节点中被进一步向下引用时,它们将被重新序列化并在此时作为引用创建。有没有办法让顶级对象被序列化为引用?我已经阅读了几个相互矛盾的帖子,似乎表明protobuf-net现在支持这一点,而其他帖子似乎建议在顶级对象周围创建一个包装器以启用此行为。感谢...

以下是显示我的问题的示例程序。如您所见,引用不相等。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProtoBuf;

namespace ProtoBufTest
{
    [ProtoContract(AsReferenceDefault=true)]
    public class Foo
    {
        [ProtoMember(1, AsReference=true)]
        public FooChild Child;

        [ProtoMember(2)]
        public Guid Id;
    }

    [ProtoContract]
    public class FooChild
    {
        [ProtoMember(1, AsReference=true)]
        public Foo Parent;
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<Foo> foos = new List<Foo>()
            {
                new Foo() { Child = new FooChild(), Id = Guid.NewGuid() }
            };

            foos[0].Child.Parent = foos[0];

            var clone = Serializer.DeepClone(foos);

            Console.WriteLine(ReferenceEquals(clone[0], clone[0].Child.Parent));
            Console.WriteLine(clone[0].Id == clone[0].Child.Parent.Id);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

如果你的确意味着根对象(即传递给Serialize的对象),那么这应该只是起作用,例如:

using ProtoBuf;
using System;
[ProtoContract]
public class Foo
{
    [ProtoMember(1)]
    public Bar Bar { get; set; }
}
[ProtoContract]
public class Bar
{
    [ProtoMember(1, AsReference = true)]
    public Foo Foo { get; set; }
}
static class Program
{
    static void Main()
    {
        var foo = new Foo { Bar = new Bar() };
        foo.Bar.Foo = foo;
        var clone = Serializer.DeepClone(foo);

        // writes: True
        Console.WriteLine(ReferenceEquals(clone, clone.Bar.Foo));
    }
}

如果正在工作,那么我怀疑它实际上并不是 root ,而只是图中的高位(但非根) - 在这种情况下,添加AsReference=true应该修复它。

请注意,我也过期了一个公开发布,但源代码现在可以更好地支持在合同级别表达这一点 - 这将包含在下一个版本中。例如(在这里从内存工作):

[ProtoContract(AsReferenceDefault=true)]
public class Foo
{
    [ProtoMember(1)]
    public Bar Bar { get; set; }
}

这隐含地假设任何Foo成员都应序列化为 ,除非 明确禁用它们(AsReference=false)。