Peut OnDeserializedAttribute être utilisé à la place de l'interface IDeserializationCallback?
-
26-09-2019 - |
Question
MSDN indique , il pouvez. Mais j'ai passé 2 heures creuser code mscorlib, car dans certains cas BinaryFormatter appelé ma méthode marquée avec AVANT constructeur désérialisation OnDeserialized. C'est, l'ordre était
OnDeserializing(StreamingContext context)
OnDeserialized(StreamingContext context)
.ctor(SerializationInfo info, StreamingContext context)
Alors que je m'y attendais pas à être
OnDeserializing(StreamingContext context)
.ctor(SerializationInfo info, StreamingContext context)
OnDeserialized(StreamingContext context)
Et le dernier point. Quand je l'interface IDeserializationCallback mis en œuvre, sa méthode OnDeserialization fut appelé constructeur, comme je voulais et attendais.
J'ai essayé de reproduire cela sur une structure de classe simple, mais tout a bien fonctionné. Dans notre projet, les objets graphique en cours de sérialisation est très complexe, donc je ne sais pas où creuser. Inspectant le code mscorlib avec réflecteur n'a pas aidé beaucoup -. Le code désérialisation me est trop compliqué pour savoir où le problème vient de
Alors, est-ce que quelqu'un sait ce qui pourrait causer ce problème? Nous utilisons l'hypothèse que OnDeserialized est appelée avant que le constructeur dans plusieurs autres endroits, donc je suis peur maintenant que ce n'est pas très fiable ...
Merci!
La solution
Enfin, j'ai la réponse à ma propre question, si quelqu'un serait intéressé. Prenons l'exemple à la fin de ce post. Il y a entre eux deux classes, les instances dont contiennent des références. Dans ces conditions, il n'y a aucune possibilité que les constructeurs désérialisation des deux instances sont passés avec des objets construits. Donc sérialiseur appelle d'abord l'un des constructeurs en passant il une instance déstructurés du second type et puis appelle le constructeur de cet objet, en passant, il construit instance de premier type. De cette manière, il nous aide à restaurer les connexions des objets, il est donc vraiment le meilleur qu'il peut faire!
Ensuite, callbacks OnDeserializing
et OnDeserialized
dans de tels cas peuvent être appelés comme je l'ai souligné dans la question, tandis que la méthode de OnDeserialization
de IDeserializationCallback
est toujours appelé après les objets COMPLETS graphique a été désérialisés, exactement comme il est indiqué dans sa spécification.
Garder tout ce qui précède à l'esprit, je trouve la meilleure utilisation à l'interface de IDeserializationCallback
faire tout traitement post-désérialisation j'ai besoin. Dans ce cas, je suis sûr que les constructeurs sont appelés pour tous les objets et je peux faire les adaptations nécessaires, d'une manière « sûre ».
[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);
}