まず、問題の簡単なテストケースとそのトリガー方法を示します。ここにクラスがあります:Protobuf.NET - トリガー参照がリストにあるときに「可能な再帰が検出される」問題
class ProtoRecurseTest
{
private int nextPayload = 1;
public int Payload { get; private set; } = 0;
public ProtoRecurseTest Back { get; private set; } = null;
public List<ProtoRecurseTest> Children { get; set; } = new List<ProtoRecurseTest>();
public ProtoRecurseTest Add()
{
ProtoRecurseTest result = new ProtoRecurseTest(this, nextPayload++);
Children.Add(result);
return result;
}
public ProtoRecurseTest()
{
}
private ProtoRecurseTest(ProtoRecurseTest parent, int payload)
{
Back = parent;
this.Payload = payload;
nextPayload = payload + 1;
}
private static void ToStringHelper(ProtoRecurseTest proto, StringBuilder sb)
{
sb.Append(proto.Payload + " -> ");
// another little hassle of protobuf due to empty list -> null deserialization
if (proto.Children != null)
{
foreach (var child in proto.Children)
ToStringHelper(child, sb);
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
ToStringHelper(this, sb);
return sb.ToString();
}
}
これは、プログラムで処理されているので、protobuf注釈はありません。 BackとChildrenと一緒にクラスが.AsReferenceDefault = trueのスキーマにすべて追加されるよう手動で確認しました。
再帰トリガーは、少なくとも8つの奇妙な深度にインスタンスが移入されたときに発生します。 7は大丈夫です。母集団コードはまっすぐです:
ProtoRecurseTest recurseTest = new ProtoRecurseTest();
ProtoRecurseTest recurseItem = recurseTest;
for (int i = 0; i < 8; i++)
recurseItem = recurseItem.Add();
そして、recurseTestをシリアル化します。この動作は、子がリストに含まれていてもリスト内にある場合にのみ発生し、リストに1つの子があっても、サンプルが入力されたコードから終了します。私が子供を単一の参照で置き換えたときには、すべてがうまく連載されました。
これはProtoBuf.NET 2.1.0.0を使用しています。