我刚刚在二进制序列化中发现了一个奇怪的行为:当我反序列化类中的字典并立即尝试向其中添加内容时,由于它没有完全初始化,我会收到一个错误:
[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
,它可以正常工作,但我不认为我应该这样做...
这种行为正常吗?有人能解释一下这里发生了什么吗?
[OnDeserialized]
属性也没有帮助。此外,我已经检查了 .NET 源代码,并根据它们的说法,在调用[OnDeserialized]
或IDeserializationCallback.OnDeserialization
之一时应该初始化所有内容。 - Alexander Yezutov