3

我刚刚注意到二进制序列化中有一个奇怪的行为:当我在我的类中反序列化一个字典并尝试立即向它添加一些东西时,我收到一个错误,因为它没有完全初始化:

[Serializable]
class Foo : ISerializable
{
    public Dictionary<int, string> Dict { get; private set; }

    public Foo()
    {
        Dict = new Dictionary<int, string>();
    }

    public Foo(SerializationInfo info, StreamingContext context)
    {
        Dict = (Dictionary<int, string>)info.GetValue("Dict", typeof(Dictionary<int, string>));
        Dict.Add(99, "test"); // Error here
    }

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

}

在我将数据添加到字典的那一行,我得到一个NullReferenceException,但该Dict属性不为空:它已实例化,但未初始化(其所有字段均为 0 或空)。我怀疑它只是用创建的FormatterServices.GetUninitializedObject,但实际上还没有反序列化。

我知道在这一点上,也许它不应该被完全初始化。所以我尝试了另一种方法,通过实现IDeserializationCallback接口。MSDN 说:

实现当前接口作为对对象图反序列化完成时调用的方法的支持的一部分。

如果一个对象需要对其子对象执行代码,可以延迟这个动作,实现IDeserializationCallback,只有在这个接口被回调时才执行代码

所以它似乎正是我所需要的,我希望我的字典在OnDeserialization被调用时被完全初始化......但我得到了同样的错误!

[Serializable]
class Foo : IDeserializationCallback
{
    public Dictionary<int, string> Dict { get; private set; }

    public Foo()
    {
        Dict = new Dictionary<int, string>();
    }

    public void OnDeserialization(object sender)
    {
        Dict.Add(99, "test"); // Error here
    }
}

由于IDeserializationCallback设计用于在子对象上执行代码,我希望此时子对象完全初始化。请注意,如果我OnDeserialize在字典上手动调用,它工作正常,但不知何故我认为我不应该这样做......

这种行为正常吗?谁能解释这里发生了什么?

4

2 回答 2

1

如果你添加Dict.OnDeserialization(sender)到你的反序列化处理程序,那么一切都会好起来的。

所以,这有效:

    [Serializable]
    class Foo : IDeserializationCallback
    {
        public Dictionary<int, string> Dict { get; private set; }

        public Foo()
        {
            Dict = new Dictionary<int, string>();
        }

        public void OnDeserialization(object sender)
        {
            // The dictionary is initialized with values in next line
            Dict.OnDeserialization(sender);
            Dict.Add(99, "test");
        }
    }
于 2011-12-11T17:13:03.770 回答
0

您需要在 OnDeserialization 处理程序中实例化您的 Dictionary<>

public void OnDeserialization(object sender)
{
    Dict = new Dictionary<int, string>();
    Dict.Add(99, "test"); // Error here
}
于 2011-12-09T15:50:42.150 回答