MSDN声明here,它可以。 但我花了2个小时挖掘mscorlib代码,因为在某些情况下,BinaryFormatter调用我的方法标记为OnDeserialized BEFORE反序列化构造函数。也就是说,订单是
OnDeserializing(StreamingContext context)
OnDeserialized(StreamingContext context)
.ctor(SerializationInfo info, StreamingContext context)
虽然我期待它
OnDeserializing(StreamingContext context)
.ctor(SerializationInfo info, StreamingContext context)
OnDeserialized(StreamingContext context)
最后一点。当我实现IDeserializationCallback接口时,其方法OnDeserialization被称为AFTER构造函数,正如我想要的那样。
我尝试在一些简单的类结构上重现这一点,但一切都运行正常。 在我们的项目中,被序列化的对象图非常复杂,所以我不知道在哪里挖掘。使用反射器检查mscorlib代码并没有多大帮助 - 反序列化代码对我来说太复杂了,无法找出问题的来源。
那么,是否有人知道可能导致此类问题的原因?我们假设OnDeserialized在其他几个地方的构造函数之前被调用,所以我现在害怕它不是很可靠......
谢谢!
答案 0 :(得分:6)
最后,如果有人有兴趣,我会回答我自己的问题。 考虑这篇文章末尾的例子。有两个类,其实例包含彼此的引用。在这种情况下,两个实例的反序列化构造函数不可能与构造对象一起传递。因此,序列化程序首先调用其中一个构造函数,将其传递给第二个类型的未构造实例,然后调用该对象的构造函数,并传递它构造的第一个类型的实例。通过这种方式,它可以帮助我们恢复对象连接,因此它确实是最好的!
接下来,在这种情况下可能会调用OnDeserializing
和OnDeserialized
回调,因为我在问题中指出,而OnDeserialization
IDeserializationCallback
方法总是在COMPLETE对象之后调用图已经反序列化,正如其规范中所述。
记住以上所有内容,我发现最好使用IDeserializationCallback
接口来进行我需要的任何后反序列化处理。在这种情况下,我确信所有对象都需要构造函数,我可以以“安全”的方式进行必要的修改。
[Serializable]
class One :ISerializable, IDeserializationCallback
{
public Two m_two;
public One() {}
public One(SerializationInfo info, StreamingContext context)
{
var two = (Two)info.GetValue("m_two", typeof(Two));
m_two = two;
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("m_two", m_two);
}
private bool m_onDeserializing;
private bool m_onDeserialized;
private bool m_callback;
public void OnDeserialization(object sender)
{
m_callback = true;
}
[OnDeserializing]
void OnDeserializing(StreamingContext context)
{
m_onDeserializing = true;
}
[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
m_onDeserialized = true;
}
}
[Serializable]
private class Two : ISerializable, IDeserializationCallback
{
public Two(){}
public One m_one;
public Two(SerializationInfo info, StreamingContext context)
{
var one = (One)info.GetValue("m_one", typeof(One));
m_one = one;
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("m_one", m_one);
}
private bool m_onDeserializing;
private bool m_onDeserialized;
private bool m_callback;
public void OnDeserialization(object sender)
{
m_callback = true;
}
[OnDeserializing]
void OnDeserializing(StreamingContext context)
{
m_onDeserializing = true;
}
[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
m_onDeserialized = true;
}
}
[STAThread]
static void Main()
{
var one = new One();
one.m_two = new Two();
one.m_two.m_one = one;
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream mss =new MemoryStream();
formatter.Serialize(mss, one);
mss.Position = 0;
var deserialize = formatter.Deserialize(mss);
}