Я пробую опцию AsReference в ProtoMember для рекурсивной ссылки.Если я создаю AnOwner с открытым конструктором, а затем сериализую / десериализую, AnOwner.Data становится нулевым.Может кто-нибудь объяснить, что происходит внутри и поддерживается ли рекурсивная ссылка?Спасибо!
[ProtoContract()]
public class SomeData
{
[ProtoMember(1, AsReference = true)]
public AnOwner Owner;
[ProtoMember(2)]
public string Value;
/// <summary>
/// ProtoBuf deserialization constructor. In fact, Serializer did not complain when this is missing
/// </summary>
private SomeData()
{
}
public SomeData(string value)
{
Value = value;
}
}
[ProtoContract()]
public class AnOwner
{
[ProtoMember(1)]
public SomeData Data;
/// <summary>
/// ProtoBuf deserialization constructor
/// </summary>
private AnOwner()
{
}
public AnOwner(SomeData data)
{
Data = data;
Data.Owner = this;
}
}
РЕДАКТИРОВАТЬ: После долгих размышлений мне удается понять это в форме этого небольшого демо, которым я поделюсь здесь.В текущей реализации (бета-версия v2) имеет значение, если для обоих задан AsReference = true, независимо от того, какой объект передан в Serializer.Serialize ().
public class Program
{
using System.IO;
using ProtoBuf;
using System;
public static void main();
{
AnOwner owner1, owner2;
AnOwner owner = new AnOwner();
SomeData data = new SomeData();
owner.Data = data;
data.Owner = owner;
string file = "sandbox.txt";
try { File.Delete(file); } catch {}; // Just in case, cos' it felt like some caching was in place.
using (var fs = File.OpenWrite(file)) { Serializer.Serialize(fs, owner); }
using (var fs = File.OpenRead(file)) { owner1 = Serializer.Deserialize<AnOwner>(fs); }
using (var fs = File.OpenRead(file)) { owner2 = Serializer.Deserialize<AnOwner>(fs); }
Console.WriteLine("SomeData.i: {0}, {1}, {2}, {3}", owner1.Data.i, owner1.Data.Owner.Data.i, owner2.Data.i, owner2.Data.Owner.Data.i);
Console.WriteLine("AnOwner.i: {0}, {1}, {2}, {3}", owner1.i, owner1.Data.Owner.i, owner2.i, owner2.Data.Owner.i);
System.Diagnostics.Debug.Assert(owner1 == owner1.Data.Owner, "1. Expect reference same, but not the case.");
System.Diagnostics.Debug.Assert(owner2 == owner2.Data.Owner, "2. Expect reference same, but not the case.");
System.Diagnostics.Debug.Assert(owner1 != owner2, "3. Expect reference different, but not the case.");
}
}
[ProtoContract()]
public class SomeData
{
public static readonly Random RAND = new Random(2);
[ProtoMember(1, AsReference = true)]
public AnOwner Owner;
// Prove that SomeData is only instantiated once per deserialise
public int i = RAND.Next(100);
public SomeData() { }
}
[ProtoContract()]
public class AnOwner
{
public static readonly Random RAND = new Random(3);
[ProtoMember(1, AsReference=true)]
public SomeData Data;
// Prove that AnOwner is only instantiated once per deserialise
public int i = RAND.Next(100);
/// <summary>
/// ProtoBuf deserialization constructor
/// </summary>
public AnOwner() { }
}