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