ILy*_*Lya 5 c# recursion serialization protobuf-net
我尝试序列化对象图(不是很深)时遇到异常.有意义的部分是这样的:
[ERROR]致命的未处理异常:ProtoBuf.ProtoException:可能的递归检测(偏移量:5级):ProtoBuf.ProtoWriter.CheckRecursionStackAndPush(object)<0x00127>处的ProtoBuf.ProtoWriter.StartSubItem(对象,ProtoBuf.ProtoWriter) ,bool)<0x0002f>
该图表示文件/目录结构,我的模型(简化)如下所示:
[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<string, PackageMember> _children;
public PackageDirectory()
{
_children = new Dictionary<string, PackageMember>();
}
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; }
}
Run Code Online (Sandbox Code Playgroud)
这棵树的深度接近10-15级,小于ProtoBuf.ProtoWriter.RecursionCheckDepth值(25).(所以也许这是一个错误?)使用的protobuf-net的版本是从trunk v2编译的版本(rev 491).
实际上,我通过修改protobuf-net代码解决了这个问题.我将值ProtoBuf.ProtoWriter.RecursionCheckDepth改为100,一切似乎都没问题.
问题是,是否有任何"真实"的方法来序列化这种图形而不修改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,
}});
Run Code Online (Sandbox Code Playgroud)
这是另一个主题,但它与所呈现的代码很好地说明.我认为在这种情况下应该允许声明私有构造函数,因为现在行为与Serializer.Deserialize(...)的行为不同.
仅当在数据中看到相同的引用(在相同路径中两次)时才抛出此异常,并且仅在深度至少时启用跟踪RecursionCheckDepth.这立刻让我怀疑的10-15深度限制引用,尽管它不一定是protobuf的处理水平的情况下相当一样的,你指望.将这个数字提高到100应该可以使它工作是没有意义的 - 事实上,这种存在RecursionCheckDepth纯粹是一种优化,以限制"典型"图形所涉及的工作量,只有在启动时才能进行更严格的检查看起来很深.
但是,我注意到这也可能表明基于继承的处理中的一些微妙的错误,也许也与此有关AsReference.我广泛使用protobuf-net,我没有看到这样的问题.如果你有一个可重现的repro我非常想看到它.
| 归档时间: |
|
| 查看次数: |
2390 次 |
| 最近记录: |