我尝试使用ToList选项序列化字典的值.
我发现在deserializtion过程中,我对所有序列化的对象都获取了null
当我使用内存流时它没有发生,当我使用.Net对象作为字典中的类型时没有发生.
下面是我创建的示例代码,用于显示问题
这段代码的输出是
字典:0-0
字典:1-1
清单:0
清单:1
字典:0-Null
字典:1-Null
清单: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;
}
}
最佳答案 Serialize支持Dictionary.这是我修改过的代码.
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>));
}
编辑:
op提到必须使用List.修改后的代码如下.无法在构造函数public A(SerializationInfo info,StreamingContext context)中初始化Dictionary dic.
因为:
无法保证对象反序列化的顺序.例如,如果一个类型引用尚未反序列化的类型,则会发生异常.如果要创建具有此类依赖关系的类型,则可以通过实现IDeserializationCallback接口和OnDeserialization方法来解决此问题.
以上para来自: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];
}
}
}
}