Problems with serializing a ToList dictionary

I tried to serialize dictionary values ​​using the ToList option. I found out that during deserialization I got zero for the whole object that I serialize. This did not happen when I used the memory stream, and this did not happen when I used the .Net object as a dictionary type. The following is an example of the code I created that shows the problem Output this code Dictionary: 0-0 Dictionary: 1-1 List: 0 List: 1 Dictionary: 0-Null Dictionary: 1-Null List: 0

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; } } 

+4
source share
1 answer

The dictionary is maintained by Serialize. here is the code i modified that works.

  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>)); } 



Edit: op mentioned should use List. Revised code as follows. The dic dictionary cannot be initialized in the public A constructor (SerializationInfo information, StreamingContext context).
Because:
The order of deserialization of objects cannot be guaranteed. For example, if one type refers to a type that has not yet been deserialized, an exception will occur. If you create types with such dependencies, you can work around this problem by implementing the IDeserializationCallback interface and the OnDeserialization method.

above para: ISerializable Interface

which means that B is not created in the constructor.

Revised Code:

 [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]; } } } } 
+2
source

Source: https://habr.com/ru/post/1396606/


All Articles