【发布时间】:2023-03-08 17:18:01
【问题描述】:
我刚刚注意到二进制序列化中的一个奇怪行为:当我在我的类中反序列化一个字典并尝试立即向其中添加一些内容时,我收到一个错误,因为它没有完全初始化:
[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,它可以正常工作,但不知何故我认为我不应该这样做......
这种行为正常吗?谁能解释这里发生了什么?
【问题讨论】:
-
我已经检查过了,事件
[OnDeserialized]属性没有帮助。此外,我检查了 .NET 源代码,并根据它们初始化所有内容,当调用[OnDeserialized]或IDeserializationCallback.OnDeserialization时 -
OnDeserialization 在整个对象图被反序列化时被调用。我怀疑真正的问题出在序列化代码中。从这里看不到。
标签: .net serialization binaryformatter ideserializationcallback