2

我正在尝试使用 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);
        }
    }
}
4

1 回答 1

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,而只是图中较高的东西(但不是 root ) - 在这种情况下添加AsReference=true应该可以解决它。

请注意,我也迟到了公开发布,但源代码现在对在合同级别表达这一点有了更好的支持——这将包含在下一个版本中。例如(在这里从记忆中工作):

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

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

于 2013-04-29T17:22:41.737 回答