オブジェクト グラフをシリアル化しようとすると例外が発生します (あまり深くはありません)。その意味のある部分は次のようになります。
[エラー] 致命的な未処理の例外: ProtoBuf.ProtoException: 再帰の可能性が検出されました (オフセット: 5 レベル): ProtoBuf.ProtoWriter.CheckRecursionStackAndPush で赤 (オブジェクト) <0x00127> で ProtoBuf.ProtoWriter.StartSubItem (オブジェクト,ProtoBuf.ProtoWriter) ,ブール) <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; }
}
このツリーの深さは 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,
}});
これは別のトピックですが、提示されたコードでよく説明されています。この場合、Serializer.Deserialize(...) の動作とは動作が異なるため、プライベート コンストラクターの宣言を許可する必要があると思います。