9

次のクラスのバイナリシリアル化を使用して保存されたデータがあります。

[Serializable]
public abstract class BaseBusinessObject
{
    private NameValueCollection _fieldErrors = new NameValueCollection();

    protected virtual NameValueCollection FieldErrors
    {
        get { return _fieldErrors; }
        set { _fieldErrors = value; }
    }

    ...
}

ある時点で、クラスは次のように変更されました。

[Serializable]
public abstract class BaseBusinessObject
{
    private Dictionary<string, string> _fieldErrors = new Dictionary<string, string>();

    protected virtual Dictionary<string, string> FieldErrors
    {
        get { return _fieldErrors; }
        set { _fieldErrors = value; }
    }

    ...
}

これにより、古いデータの逆シリアル化で問題が発生します。

私が最初に考えたのは実装することでしたISerializableが、このクラスには多数のプロパティと、これを実装する必要のある数百の継承クラスがあります。

デシリアライズ中に現在の構造に一致するように古いデータを変更するか、古いデータをクリーンにアップグレードする方法が必要です。

4

4 に答える 4

5

fieldErrors新しい _を別の名前で追加して、たとえば_fieldErrors2、 にし[Optional]ます。次に、(存在する場合) からデータをコピーするメソッドを実装し、_fieldErrors[OnDeserialized]をクリアします。_fieldErrors_fieldErrors2

于 2009-08-11T15:11:59.093 に答える
3

データが内部でのみ使用される場合、私の最初の考えは、古い「NameValueCollection」を使用してバイナリ データを逆シリアル化し、それを Dictionnary にマップして再シリアル化する単純な使い捨てコードを作成することです。すべてのデータを処理するのに数日かかるとしても、古いデータをサポートするために新しいコードにパッチを実装する価値はないようです。

内部でのみ使用されていなくても、インポーターは最も簡単な方法のようです。

于 2009-08-11T14:52:03.963 に答える
2

OlivierD の良いアドバイスに加えて、両方のクラスを定義することをお勧めしますが、最初は現在のバージョンとしてデシリアライズしてみてください。catch ブロックで、レガシー バージョンとしてデシリアライズし、現在のものにアップグレードして保存します。レガシー バージョンのインスタンスが存在しない場合は、コードを削除できます。

于 2009-08-11T14:59:57.507 に答える
0

いくつかのオプションを調査した後、次の結論を下しました。

理想的には、元の値にアクセスしてNameValueCollection、手動で に変換できDictionary<string, string>ます。これを行う唯一の方法は を実装することですISerializableが、これには 2 つの大きな問題がありました。それは、レガシー データの名前付けの一致と、すべての継承クラス (何百もあるクラス) のシリアライゼーション ロジックの組み込みです。

事実上、これは私を縛り付けました。幸いなことに、このフィールドは実際にはフォーム検証エラーの要約としてのみ使用され、そもそもシリアル化されるべきではないと判断できたため、シリアル化から除外しました。

于 2009-08-11T20:31:18.670 に答える