1

一連のオブジェクトのシリアル化に対処する必要があります。簡単にするために、[Serializable]属性をバイナリ シリアライザとバイナリ フォーマッタと一緒に使用し[NonSerialized]、ほとんどのもので不要なフィールドを除外しています。より複雑な部分については、ISerializableインターフェイス + デシリアライズ コンストラクターを実装しました。これは、循環参照 (通常のオブジェクト参照の形式) がある場合でも、非常にうまく機能します。

今、私は少し混乱する何かにぶつかりました。Bを実装しISerializable、別のクラス (名前を付けます) によって参照されているContainerクラスがそのクラスのイベントをサブスクライブすると、シリアライズ時に のGetObjectData-Method がB正確に 2 回呼び出されます。

[Serializable]
class Container
{
    B subObj;
    public int X;
    public event EventHandler E;

    public Container()
    {
        subObj = new B(this);
    }

}

[Serializable]
class B : ISerializable
{
    private Container parent;

    public B(Container parent) {
        this.parent = parent;

        parent.E += (sender, e) => { Console.WriteLine(this.parent.X); };
    }

    protected B(SerializationInfo info, StreamingContext context) { }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        Console.WriteLine("GetObjectData");
    }
}

したがって、このコード例は次のように記述します

GetObjectData
GetObjectData

循環効果の問題については、スタックオーバーフローか何かを期待していたでしょう:-)。それにもかかわらず、良くありません。もちろん、この例の回避策は、逆シリアル化コンストラクターにイベントを再度追加することです。しかし、私はこれを引き起こした原因を突き止めたいと思います。

最後に 1 つ: 上記のラムダ式の参照を次のように変更すると (フィールドではなくパラメーターを参照する)...

parent.E += (sender, e) => { Console.WriteLine(parent.X); };

... シリアライゼーションは、初回実行直後にSerializationException( B+<>c__DisplayClass2 is not mark as SerializableGetObjectData ) でクラッシュします。

理由のヒント (および有用な回避策) を歓迎します。

4

0 に答える 0