Dictionary ToList序列化的问题

时间:2012-02-15 12:05:59

标签: c# generics serialization dictionary

我尝试使用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;
    }
}

1 个答案:

答案 0 :(得分:2)

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方法来解决此问题。

以上来自: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];
            }
        }
    }
}