我刚刚注意到二进制序列化中有一个奇怪的行为:当我在我的类中反序列化一个字典并尝试立即向它添加一些东西时,我收到一个错误,因为它没有完全初始化:
[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
在字典上手动调用,它工作正常,但不知何故我认为我不应该这样做......
这种行为正常吗?谁能解释这里发生了什么?