Banana List 包含对 Fruits List 中对象的引用。水果列表中的香蕉一个接一个地放置。此外,它们具有递增的数字。(添加和删除香蕉应该保留这些属性) 问题是在反序列化后 Bananas List 和 Fruits List in Basket 似乎包含不同的对象。有办法避免吗?
我的第二个问题是关于 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; }
}
Marc Gravell 给出的更新#1答案对上述问题非常有效。但我的目标功能是容器字典,它给出了一个例外:“反序列化期间引用跟踪的对象更改了引用”。下面列出的更改适用于 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)]
to更改为[ProtoMember(1, OverwriteList = true)]
有助于解决异常,但引用 ContainedBy 会丢失。