奇怪的反序列化错误,子对象未完全反序列化

时间:2011-12-09 11:26:11

标签: .net serialization binaryformatter ideserializationcallback

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

[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属性不为null:它被实例化,但没有初始化(它的所有字段都是0或null )。我怀疑它只是用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,它可以正常工作,但我不认为我应该这样做......

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

2 个答案:

答案 0 :(得分: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");
        }
    }

答案 1 :(得分:0)

您需要实例化您的词典&lt;&gt;在OnDeserialization处理程序

public void OnDeserialization(object sender)
{
    Dict = new Dictionary<int, string>();
    Dict.Add(99, "test"); // Error here
}