【问题标题】:Deserializing .NET Dictionary using ISerializable使用 ISerializable 反序列化 .NET 字典
【发布时间】:2016-05-17 12:50:08
【问题描述】:

在封闭类中实现 ISerializable 时,我在获得 Dictionary 的反序列化/序列化工作时遇到问题。如果我只应用 SerializableAttribute,它似乎能够自动反序列化。但是,我需要在此过程中检查反序列化字典,因此我需要 ISerializable 才能工作。

我设置了一个小测试,以确保它不是由于其他一些问题。 Test 类如下所示:

[Serializable]
class Test : ISerializable
{
    private Dictionary<string, int> _dict;

    public Test()
    {
        var r = new Random();
        _dict = new Dictionary<string, int>()
        {
            { "one", r.Next(10) },
            { "two", r.Next(10) },
            { "thr", r.Next(10) },
            { "fou", r.Next(10) },
            { "fiv", r.Next(10) }
        };
    }

    protected Test(SerializationInfo info, StreamingContext context)
    {
        // Here _dict.Count == 0
        // So it found a Dictionary but no content?
        _dict = (Dictionary<string, int>)info.GetValue("foo", typeof(Dictionary<string, int>));
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("foo", _dict, typeof(Dictionary<string, int>));
    }

    public override string ToString()
    {
        var sb = new StringBuilder();
        foreach (var pair in _dict)
            sb.Append(pair.Key).Append(" : ").Append(pair.Value).AppendLine();
        return sb.ToString();
    }
}

还有 ma​​in 来测试它:

static void Main(string[] args)
{
    var t1 = new Test();
    Console.WriteLine(t1);
    var formatter = new BinaryFormatter();
    using (var stream = new FileStream("test.test", FileMode.Create, FileAccess.Write, FileShare.None))
        formatter.Serialize(stream, t1);

    Test t2;
    using (var stream = new FileStream("test.test", FileMode.Open, FileAccess.Read, FileShare.Read))
        t2 = (Test)formatter.Deserialize(stream);
    Console.WriteLine(t2);
    Console.ReadLine();
}

控制台中的输出前后一致。但正如 Test 类中所述,重载的构造函数不会读取反序列化字典中的任何内容。

我做错了什么还是这是一个错误/微妙的副作用?

【问题讨论】:

  • 我的问题不在于是否可以序列化,而是如何“控制”序列化过程(使用 ISerializable 的实现),这似乎失败了。跨度>
  • @OrelEraki:OP 询问二进制序列化,特别是反序列化实例的有效性。提供的链接不涉及此特定区域。
  • @OrelEraki:我确实浏览了答案。第二个链接中的答案没有解决字典二进制序列化作为复合对象的成员,这是这个问题的本质。

标签: c# .net dictionary serialization


【解决方案1】:

Dictionary&lt;TKey, TValue&gt; 实现IDeserializationCallback 并将其反序列化的完成推迟到整个对象图被读回。你可以在Reference Source 上看到它是如何实际实现的:

protected Dictionary(SerializationInfo info, StreamingContext context)            

{
    //We can't do anything with the keys and values until the entire graph has been deserialized
    //and we have a resonable estimate that GetHashCode is not going to fail.  For the time being,
    //we'll just cache this.  The graph is not valid until OnDeserialization has been called.
    HashHelpers.SerializationInfoTable.Add(this, info);
}

在您的代码中强制完成调用_dict.OnDeserialization()

protected Test(SerializationInfo info, StreamingContext context)
{
    // Here _dict.Count == 0
    // So it found a Dictionary but no content?
    _dict = (Dictionary<string, int>)info.GetValue("foo", typeof(Dictionary<string, int>));

    _dict.OnDeserialization(null);

    // Content is restored.
    Console.WriteLine("_dict.Count={0}", _dict.Count);
}

PS:HashSet&lt;T&gt;SortedSet&lt;T&gt;LinkedList&lt;T&gt; 可能很少有其他容器类型表现出相同的行为

【讨论】:

  • 太好了,谢谢!现在可以了。也谢谢你的链接,不知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-01
  • 2014-02-01
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
相关资源
最近更新 更多