2012-02-15 88 views
4

我試圖使用ToList選項序列化字典的值。 我發現在反序列化過程中,我在所有序列化的對象上都得到了空值 當我使用內存流時,它沒有發生,當我使用.Net對象作爲字典中的類型時,它沒有發生。 下面是我創建,顯示該問題的示例碼本 代碼的輸出是 字典:0-0 詞典:1-1 列表:0 列表:1 字典:0-空 詞典:1-空 列表:0字典ToList序列化的問題

class Program 
{ 
    static void Main(string[] args) 
    { 
     A state = new A(); 

     Stream stream = File.Open("D:\\temp\\temp.txt", FileMode.Create); 
     BinaryFormatter bFormatter = new BinaryFormatter(); 
     bFormatter.Serialize(stream, state); 
     stream.Close(); 

     state.PrintData(); 

     stream = File.Open("D:\\temp\\temp.txt", FileMode.Open); 
     bFormatter = new BinaryFormatter(); 
     state = (A)bFormatter.Deserialize(stream); 
     stream.Close(); 

     state.PrintData(); 
    } 
} 

[Serializable()] 
public class A : ISerializable 
{ 
    Dictionary<int, B> dic = new Dictionary<int, B>(); 
    List<B> list = new List<B>(); 

    public A() 
    { 
     for (int i = 0; i < 4; i++) 
     { 
      dic.Add(i, new B(i)); 
      list.Add(new B(i)); 
     } 
    } 

    public void PrintData() 
    { 
     foreach (KeyValuePair<int, B> kvp in dic) 
     { 
      Console.WriteLine("Dictionary: " + kvp.Key.ToString() + "-" + ((kvp.Value != null) ? kvp.Value.ToString() : "Null")); 
     } 
     foreach(B b in list) 
     { 
      Console.WriteLine("List: " + b.ToString()); 
     } 
    } 

    public A(SerializationInfo info, StreamingContext context) 
    { 
     List<int> keys = info.GetValue("keys", typeof(List<int>)) as List<int>; 
     List<B> values = info.GetValue("values", typeof(List<B>)) as List<B>; 

     int count = keys.Count; 
     if(count == values.Count) 
     { 
      for(int i = 0; i < count; i++) 
      { 
       dic[keys[i]] = values[i]; 
      } 
     } 

     list = info.GetValue("list", typeof(List<B>)) as List<B>; 
    } 

    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     info.AddValue("keys", dic.Keys.ToList(), typeof(List<int>)); 
     info.AddValue("values", dic.Values.ToList(), typeof(List<B>)); 
     List<B> listFromDic = new List<B>(dic.Values.ToList()); 
     info.AddValue("list", listFromDic, typeof(List<B>)); 
    } 
} 

[Serializable()] 
public class B : ISerializable 
{ 
    int foo; 

    public B(int i) 
    { 
     foo = i; 
    } 

    public B(SerializationInfo info, StreamingContext context) 
    { 
     foo = info.GetInt32("foo"); 
    } 

    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     info.AddValue("foo", foo); 
    } 

    public override string ToString() 
    { 
     return (foo != null) ? foo.ToString() : String.Empty; 
    } 
} 

+0

爲什麼你想序列化的字典作爲一個列表? Dictionary是直接可串行化的。 – svick 2012-02-15 13:45:54

+1

,因爲在.NET4中字典序列化已更改,並且支持舊串行化存在問題 – 2012-02-15 14:50:30

+0

嗨,Shimi,您會喜歡在問題中突出顯示「字典序列化已在.NET4中更改,並且支持舊序列化存在問題」 。所以其他觀衆會知道這一點。我認爲.net 4的向前兼容性比.net 2.0更好 – findcaiyzh 2012-02-15 22:39:55

回答

2

字典被序列化的支持。這裏是我修改後的代碼。

public A(SerializationInfo info, StreamingContext context) 
    { 
     dic = info.GetValue("mapping", typeof(Dictionary<int, B>)) as Dictionary<int, B>; 
     list = info.GetValue("list", typeof(List<B>)) as List<B>; 
    } 

    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     info.AddValue("mapping", dic, typeof(Dictionary<int, B>)); 
     List<B> listFromDic = new List<B>(dic.Values.ToList()); 
     info.AddValue("list", listFromDic, typeof(List<B>)); 
    } 



編輯:提到必須使用目錄 運算。修改後的代碼如下。字典dic無法在構造函數public A(SerializationInfo info,StreamingContext context)中初始化。
因爲:
無法保證對象被反序列化的順序。例如,如果一個類型引用尚未反序列化的類型,則會發生異常。如果您正在創建具有此類依賴性的類型,則可以通過實現IDeserializationCallback接口和OnDeserialization方法來解決該問題。

以上對來自:ISerializable Interface

這意味着B沒有創建在A的構造。

修訂代碼:

[Serializable()] 
public class A : ISerializable, IDeserializationCallback 
{ 
    Dictionary<int, B> dic = new Dictionary<int, B>(); 
    List<B> list = new List<B>(); 
    private List<int> keys = new List<int>(); 

    public A() 
    { 
     for (int i = 0; i < 4; i++) 
     { 
      dic.Add(i, new B(i)); 
      list.Add(new B(i)); 
     } 
    } 

    public void PrintData() 
    { 
     foreach (KeyValuePair<int, B> kvp in dic) 
     { 
      Console.WriteLine("Dictionary: " + kvp.Key.ToString() + "-" + ((kvp.Value != null) ? kvp.Value.ToString() : "Null")); 
     } 
     foreach (B b in list) 
     { 
      Console.WriteLine("List: " + b.ToString()); 
     } 
    } 

    public A(SerializationInfo info, StreamingContext context) 
    { 
     keys = info.GetValue("keys", typeof(List<int>)) as List<int>; 
     List<B> values = info.GetValue("values", typeof(List<B>)) as List<B>; 

     list = info.GetValue("list", typeof(List<B>)) as List<B>; 
    } 

    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     info.AddValue("keys", dic.Keys.ToList(), typeof(List<int>)); 
     info.AddValue("values", dic.Values.ToList(), typeof(List<B>)); 
     List<B> listFromDic = new List<B>(dic.Values.ToList()); 
     info.AddValue("list", listFromDic, typeof(List<B>)); 
    } 

    public void OnDeserialization(object sender) 
    { 
     dic = new Dictionary<int, B>(); 
     int count = keys.Count; 
     if (count == list.Count) 
     { 
      for (int i = 0; i < count; i++) 
      { 
       dic[keys[i]] = list[i]; 
      } 
     } 
    } 
} 
+0

+1,尼斯。適用於我。順便說一句,在'A()'構造函數中刪除註釋掉的代碼,這樣答案的質量會更好 – sll 2012-02-15 13:18:25

+0

我沒有使用字典序列化,因爲字典序列化在.NET4中已更改,並且存在支持舊序列化的問題 – 2012-02-15 17:12:34