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 に答える