protobuf-net:检测到可能的递归

我尝试序列化对象图(不是很深)时遇到exception。 有意义的部分是这样的:

[错误]致命的未处理exception:ProtoBuf.ProtoException:可能的递归检测(偏移量:5级):ProtoBuf.ProtoWriter.CheckRecursionStackAndPush(object)处的ProtoBuf.ProtoWriter.StartSubItem(对象,ProtoBuf.ProtoWriter) ,bool)

该图表示文件/目录结构,我的模型(简化)如下所示:

[ProtoContract] [ProtoInclude(100, typeof(PackageDirectory))] [ProtoInclude(200, typeof(PackageFile))] public abstract class PackageMember { [ProtoMember(1)] public virtual string Name { get; protected set; } [ProtoMember(2, AsReference=true)] public PackageDirectory ParentDirectory { get; protected set; } } [ProtoContract] public class PackageDirectory : PackageMember { [ProtoMember(3)] private Dictionary _children; public PackageDirectory() { _children = new Dictionary(); } public PackageDirectory (string name, PackageDirectory parentDirectory) : this() { this.ParentDirectory = parentDirectory; this.Name = name; } public void Add (PackageMember member) { _children.Add(member.Name, member); } } [ProtoContract] public class PackageFile : PackageMember { private Stream _file; private BinaryReader _reader; private PackageFile() {} public PackageFile (string name, int offset, int length, PackageDirectory directory, Stream file) { this.Name = name; this.Length = length; this.Offset = offset; this.ParentDirectory = directory; _file = file; _reader = new BinaryReader(_file); } [OnDeserialized] protected virtual void OnDeserialized(SerializationContext context) { var deserializationContext = context.Context as DeserializationContext; if (deserializationContext != null) { _file = deserializationContext.FileStream; _reader = new BinaryReader(_file); } } [ProtoMember(3)] public int Offset { get; private set; } [ProtoMember(4)] public int Length { get; private set; } } 

这棵树的深度接近10-15级,小于ProtoBuf.ProtoWriter.RecursionCheckDepth值(25)。 (所以也许这是一个错误?)使用的protobuf-net版本是从trunk v2rev 491 )编译的版本

实际上,我通过修改protobuf-net代码解决了这个问题。 我将ProtoBuf.ProtoWriter.RecursionCheckDepthProtoBuf.ProtoWriter.RecursionCheckDepth为100,一切似乎ProtoBuf.ProtoWriter.RecursionCheckDepth

问题是,是否有任何“真实”的方法来序列化这种图形而不修改protobuf代码? 这种行为是正确的还是一个错误?

我的平台是Windows 7 Professional 64位上的Mono-2.10-8

PS我还发现,如果我使用下面的代码进行deserizlie,我应该将PackageDirectory无参数构造函数公开。

 var value = new PackageDirectory(); RuntimeTypeModel.Default.Deserialize(ms, value, typeof(PackageDirectory), new SerializationContext { Context = new DeserializationContext { FileStream = _file, }}); 

这是另一个主题,但它与所呈现的代码很好地说明了。 我认为在这种情况下应该允许声明私有构造函数,因为现在行为与Serializer.Deserialize(…)的行为不同。

仅当在数据中看到相同的引用 (在同一路径中两次)时才会抛出此exception,并且当深度至少为RecursionCheckDepth 时才启用跟踪。 这立刻让我怀疑所引用的10-15深度限制,尽管并不一定是protobuf处理的水平与您计算的水平完全相同。 将这个数字提高到100应该可以使它起作用是没有意义的 – 事实上,这个RecursionCheckDepth存在纯粹是一种优化,以限制“典型”图形所涉及的工作量,只有这样才能进行更严格的检查开始看起来很深。

但是,我注意到这也可能表明基于inheritance的处理中存在一些微妙的错误,也许也与AsReference有关。 我广泛使用protobuf-net,我没有看到这样的问题。 如果你有一个可重复的repro我非常想看到它。