2009-08-11 102 views
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

以不同的名稱添加新的_ fieldErrors,例如_fieldErrors2,並將其設置爲[Optional]。然後執行[OnDeserialized]方法,將_fieldErrors中的數據複製到_fieldErrors2(如果存在),並清除_fieldErrors。

+0

這爲我的需求提供了最現實的方法,但我最終走向了另一條路線。 – ramnik 2009-08-11 20:22:22

3

如果數據僅用於內部,我的第一個想法是編寫一些簡單的一次性代碼,使用舊的「NameValueCollection」對二進制數據進行反序列化,將其映射到一個Dictionnary並重新序列化它。即使處理所有數據需要幾天的時間,但在您的新代碼上實施補丁以支持舊數據似乎也不值得。

即使它不僅在內部使用,進口商似乎是最簡單的方法。

2

添加到OlivierD的好建議,我建議你定義這兩個類,但最初嘗試反序列化爲當前版本。在您的catch塊中,將其反序列化爲舊版本,然後將其升級到當前版本並將其保存回去。如果不存在舊版本的實例,則可以刪除代碼。

0

調查幾個選項後,我做了以下結論:

理想我想能夠從原來的NameValueCollection訪問值,並手動將其轉換爲Dictionary<string, string>。要做到這一點的唯一方法是實現ISerializable,但是這提出了兩個主要問題:匹配到遺留數據的命名以及爲所有繼承類(其中有數百個)包含序列化邏輯。

實際上,這讓我陷入了一種束縛。幸運的是,我能夠確定此字段實際上僅用作表單驗證錯誤的摘要,不應該首先獲得序列化,因此我已將其排除在序列化之外。