3

私はこのようなクラスを持っています:

public class Foo
{
    public IBar {get;set;}
    //tons of other properties
}

public interface IBar
{
    //whatever
}

クラスは、バイナリのシリアル化 (BinaryFormatter の標準的な使用) に使用されます。IBar の実装は [Serializable] とマークされているため、すべてが機能します。

ここで、Bar をシリアライズせず、後方互換性を維持したいと考えています (コード内では参照されていませんでした)。 NonSerialized属性で十分のようです。ただし、自動プロパティではなく、フィールドにのみ適用できます。だから私はこれを試しました:

public class Foo
{
    private IBar _bar;
    [NonSerializable]
    public IBar Bar 
    {
        get { return _bar; }
        set { _bar = value; }
    }
}

驚くべきことに、これはうまく機能します。古い Foo と新しい Foo の両方を逆シリアル化できます。

私の質問は、これらがシリアル化されたフィールドであり、自動プロパティのバッキング フィールドの名前に C# 以外の文字が含まれている可能性がある場合、どのように機能するのでしょうか?

言い換えると:

古い Foo の IBar フィールド名 (私の推測): k__BackingField

新しい Foo の IBar フィールド名: _bar

明らかにそれらは一致しないので、BinaryFormatter はこれをどのように克服するのでしょうか?

4

1 に答える 1

1

あなたの例には何か奇妙なことがあると思います。BinaryFormatterはこれを処理できないはずです(これが4.5で変更されていない限り、私が知る限り)。そのため、下位互換性が必要な場合に使用するのは非常に危険です。値が古いバージョンからシリアル化され、新しいバージョンに逆シリアル化されていることを確認しますか?デシリアライズされたデータが一致し、nullではないことを確認できますか?

動作しないことを確認するプログラムの完全な例については、こちらを参照してください。 http://www.infragistics.com/community/blogs/josh_smith/archive/2008/02/05/automatic-properties-and-the-binaryformatter.aspx

例外は表示されませんが、xyz__backingfieldという名前のフィールドの古い値は失われ、新しいクラスではデフォルト値に置き換えられます。

下位互換性が必要な場合は、自動プロパティの使用を避けてください。そうしないと、すぐに問題が発生します。実際、デフォルト(自動)モードのBinaryFormatterは、オブジェクトをシリアル化し、同じアプリケーションでオブジェクトを再度逆シリアル化する場合、たとえばコピーアンドペーストや同様の操作でのみ非常に役立つため、実際には問題ではありません。その場合、シリアル化と逆シリアル化の両方を実行するのは同じコードになるため、バージョン管理の問題は発生しません。

気を失うことなくシリアル化の下位互換性を確保するには、スキーマを完全に制御できることを確認してください。トラブルに巻き込まれない可能性が十分にあるシリアライザーの良い例は、DataContractSerializer、Json.NET、またはプロトコルバッファー(protobuf-netなど)です。

最後の可能性として、ISerializableを実装し、BinaryFormatterのディクショナリストレージを使用できますが、とにかくシリアル化を手動でロールすることにはすべての欠点があります。

補足として、属性をバッキングフィールドに適用する場合は、[field:AttriuteType]を試してください。これは、たとえば、イベントのバッキングフィールドをシリアル化されていないものとしてマークするのに役立ちます。

于 2013-02-28T12:20:26.480 に答える