Banana List には、Fruits List 内のオブジェクトへの参照が含まれています。Fruits List のバナナが次々と配置されます。さらに、昇順の数字があります。(バナナの追加と削除はこれらのプロパティを保持する必要があります) 問題は、デシリアライズ後、Basket の Bananas List と Fruits List に異なるオブジェクトが含まれているように見えることです。それを回避する方法はありますか?
2 番目の質問は、Banana の ContainedBy プロパティに関するものです。Cos Bananas は、特定のコンテナーを指している場所を認識していますが、逆シリアル化の後、神がどこを指しているのか (それらが含まれているバスケット以外のバスケットに固有であるため) を示しています。キャッチはどこですか?
[ProtoContract]
[ProtoInclude(500, typeof(Basket))]
public interface IContainer
{
[ProtoMember(1, OverwriteList = true)]
public List<Banana> Bananas { get; set; }
[ProtoMember(2, OverwriteList = true)]
public List<IFruit> Fruits { get; set; }
}
[ProtoContract]
public class Basket : IContainer
{
[ProtoMember(1, OverwriteList = true)]
public List<Banana> Bananas { get; set; }
[ProtoMember(2, OverwriteList = true)]
public List<IFruit> Fruits { get; set; }
public void AddBanana()
{
var number = Bananas.Count;
var newBanana = new Banana(number) {ContainedBy = this};
var lastBanana = Bananas[Bananas.Count - 1];
var index = Fruits.LastIndexOf(lastBanana);
Friuts.Insert(index + 1, newBanana);
Bananas.Add(newBanana);
}
public void DeleteBanana(Banana banana)
{
Bananas.Remove(banana);
Fruits.Remove(banana);
var n = 0;
foreach (var b in Bananas)
{
b.Number = n++;
}
}
}
[ProtoContract]
[ProtoInclude(600, typeof(Banana))]
public interface IFruit
{
[ProtoMember(1, AsReference = true)]
IContainer ContainedBy { get; set; }
}
[ProtoContract]
public class Banana : IFruit
{
[ProtoMember(1)]
public int Number { get; set; }
[ProtoMember(2, AsReference = true)]
IContainer ContainedBy { get; set; }
}
更新 #1 Marc Gravell による回答は、上記の問題に対して非常にうまく機能します。しかし、私のターゲット機能はコンテナのディクショナリであり、例外が発生します:「逆シリアル化中に参照追跡オブジェクトが参照を変更しました」。以下にリストされている変更は、Marc Gravell の回答に適用されます。
[ProtoContract]
class RootObject
{
[ProtoMember(1, OverwriteList = true, AsReference = true)]
public Dictionary<string, IContainer> Dictionary { get; set; }
}
...
internal static class Program
{
private static void Main()
{
var basketA = new Basket();
basketA.AddBanana();
var basketB = new Basket();
basketB.AddBanana();
var root = new RootObject {Dictionary = new Dictionary<string, IContainer>()};
root.Dictionary.Add("A",basketA);
root.Dictionary.Add("B",basketB);
RootObject clone;
using (var file = File.Create("tmp.bin"))
{
Serializer.Serialize<RootObject>(file, root);
}
using (var file = File.OpenRead("tmp.bin"))
{
clone = Serializer.Deserialize<RootObject>(file);
}
foreach (var container in clone.Dictionary.Values) //Exception
{
Console.WriteLine(container.Bananas.Count == container.Fruits.Count); //true
Console.WriteLine(ReferenceEquals(
container.Bananas[0],
container.Fruits[0])); // true
Console.WriteLine(ReferenceEquals(
container.Fruits[0].ContainedBy,
container)); // false
}
}
}
明らかに、RootObject の Dictionary タグを から に変更[ProtoMember(1, OverwriteList = true, AsReference = true)]
する[ProtoMember(1, OverwriteList = true)]
と例外が発生しますが、参照 ContainedBy は失われます。