The _parent and Value_nodes parameters point to the same type (PrefixTree), but only _parent is marked as "AsReference".
If you go on the serialization stack, you will see that the value of the dictionary value is serialized regardless of the _parent element and is not checked for duplicate instance.
When he walks the tree, an internal check is performed on the depth of serialization 25, at which he begins to detect duplicate instances. If this value were greater, it would not throw an exception; if it were less, it would select a node above the tree.
I also do not think that this would be deserializable, and, of course, if this happened, the value of the _parent field for each child node would not be the same instance as the _nodes container.
You need to create your own type of dictionary (a subclass of Dictionary <,> or implement IDictionary <,>) so that you can add the [ProtoContract] attribute and control the serialization of dictionary entries.
t
[ProtoContract] public class NodeItem { [ProtoMember(1)] public char Key { get; set; } [ProtoMember(2, AsReference = true)] public PrefixTree Value { get; set; } } [ProtoContract] public class Nodes : IDictionary<char, PrefixTree> { private readonly IDictionary<char, PrefixTree> inner; [ProtoMember(1)] public NodeItem[] Items { get { return this.inner.Select(item => new NodeItem() {Key = item.Key, Value = item.Value}).ToArray(); } set { foreach( NodeItem item in value) { this.inner.Add(item.Key, item.Value); } } } ...
the key here is to get AsReference metadata attached to PrefixTree nodes. Also note that the elements return an array, if you want it to be a list, then you need to use the OverwriteList attribute parameter.
I also needed to remove the readonly keyword for each field in the PrefixTree type. This unit test passed for me.
[TestMethod] public void TestMethod1() { var tree = new PrefixTree(); tree.Add("racket".ToCharArray()); tree.Add("rambo".ToCharArray()); PrefixTree tree2 = null; using (var stream = new MemoryStream()) { Serializer.Serialize(stream, tree); stream.Position = 0; tree2 = Serializer.Deserialize<PrefixTree>(stream); } Assert.IsNotNull(tree2); Assert.AreEqual(tree._nodes.Count, tree2._nodes.Count); Assert.AreEqual(2, tree2._nodes['r']._nodes['a']._nodes.Count);