Наконец, у меня есть ответ на свой вопрос, если кому-то будет интересно.
Рассмотрим пример в конце этого поста. Есть два класса, экземпляры которых содержат ссылки друг на друга. При таких условиях невозможно, чтобы десериализованные конструкторы обоих экземпляров были переданы с построенными объектами. Таким образом, сериализатор сначала вызывает один из конструкторов, передавая ему неструктурированный экземпляр второго типа, а затем вызывает конструктор этого объекта, передавая ему созданный экземпляр первого типа. Таким образом, это помогает нам восстановить соединения объектов, так что это действительно лучшее, что он может сделать!
Далее, OnDeserializing
и OnDeserialized
обратные вызовы в таких случаях могут быть вызваны, как я указал в вопросе, в то время как OnDeserialization
метод IDeserializationCallback
всегда вызывается после десериализации графа ПОЛНЫХ объектов, точно так же, как он указано в его спецификации.
Имея в виду все вышесказанное, я считаю, что лучше всего использовать интерфейс 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);
}