2012-04-19 69 views
6

改變了我有這個類戰略反序列化類,在.NET

[Serializable] 
public class myClass() : ISerializable 
{ 
    public int a; 
    public int b; 
    public int c; 

    public void GetObjectData(SerializationInfo info, 
           StreamingContext context) 
     { 
     // Some code 
     } 

    public myClass(SerializationInfo info, 
        StreamingContext context) 
     { 
     // Some code 
     } 
} 

我有數百個這樣的對象在我的數據庫。我現在已經準備好發佈我的應用程序的新版本,其中類已經演變到

[Serializable] 
public class myClass() : ISerializable 
{ 
    public int a; 
    public string b; 
    public int c; 
    public bool d; 

    public void GetObjectData(SerializationInfo info, 
           StreamingContext context) 
     { 
     // Some code 
     } 

    public myClass(SerializationInfo info, 
        StreamingContext context) 
     { 
     // Some code 
     } 
} 

如何將一個反序列化基於第一版本與第二的反序列化構造函數序列化的對象。

是否還有未來的版本打樣我的第二個版本的類的策略?

+1

做一個轉換程序,讀取第一種類型的對象產生第二種類型的對象,並用新的替換舊的對象。如果你正在談論數百個,而不是數百萬條記錄,那麼運行該程序應該花費很長時間。 – dasblinkenlight 2012-04-19 22:45:14

+2

有一個關於它的專門的MSDN文章。最好從這裏開始:http://msdn.microsoft.com/en-US/library/ms229752%28v=vs.90%29.aspx – 2012-04-19 23:32:57

回答

4

沒有準備你的一部分,你可能需要求助於黑客攻擊:當你的public myClass反序列化的構造函數得到的bool d值,封閉代碼try/catch,並設置d爲默認值,當你發現一個異常。

在未來,添加int"__ver"(或不與您傳遞給info.AddValue參數碰撞任何其他名稱),並將其設置爲一個常數,你在你的類保持指示在兼容和不兼容的改變系列化:

public class myClass : ISerializable { 
    private const int __ver = 4; 
    public int a; 
    public string b; 
    public int c; 
    public bool d; 

    public void GetObjectData(SerializationInfo info, 
          StreamingContext context) { 
     info.AddValue("__ver", ver); 
     info.AddValue("a", a); 
     // and so on 
    } 

    public myClass(SerializationInfo info, 
       StreamingContext context) { 
     switch(info.GetInt32("__ver")) { 
      case 3: 
       // Deserialize prior version 
      break; 
      case 4: 
       // Deserialize current version 
      break; 
     } 
    } 
} 
+0

唯一的問題是數據庫中的所有當前實例都沒有__ver字段,所以你不能改造這個實現。 – 2012-04-19 23:27:00

+0

'SerializationInfo'沒有類似'ContainsKey()'的東西?我認爲這在這裏會非常有用。 – svick 2012-04-19 23:45:17

+0

我想你可以使用'MemberCount'或'GetEnumerator()'來避免'try' /'catch'。 – svick 2012-04-19 23:47:10

2

序列化類是偉大的周圍使它們穿過同一版本的軟件,但使用它的持久性,當你趕緊打這個問題。如果要將對象存儲爲BLOBs,則可以使用諸如protobuf-net之類的東西,通過允許可選字段允許序列化版本控制。

鑑於你目前的困境都可以做,以得到它的imediatly的工作是把一個嘗試捕捉圍繞新的字段,然後默認他們,如果他們是不是有:

protected myClass(SerializationInfo info, StreamingContext context) 
{ 
    c = info.GetInt32("Value_C"); 
    try 
    { 
     b = info.GetBoolean("Value_B"); 
    } 
    catch (SerializationException) 
    { 
     b = true; 
    } 
}