Comportement étrange de la sérialisation binary .NET sur Dictionary

J’ai rencontré un comportement étrange, du moins selon mes attentes, dans la sérialisation binary de .NET.

Tous les éléments d’un Dictionary chargés sont ajoutés à leur parent APRES le rappel OnDeserialization . En revanche, List fait l’inverse. Cela peut être très gênant dans le code d’un référentiel réel, par exemple lorsque vous devez append des delegates à des éléments de dictionnaire. S’il vous plaît vérifier le code exemple et regarder les assertions.

Est-ce un comportement normal?

 [Serializable] public class Data : IDeserializationCallback { public List List { get; set; } public Dictionary Dictionary { get; set; } public Data() { Dictionary = new Dictionary { { "hello", "hello" }, { "CU", "CU" } }; List = new List { "hello", "CU" }; } public static Data Load(ssortingng filename) { using (Stream stream = File.OpenRead(filename)) { Data result = (Data)new BinaryFormatter().Deserialize(stream); TestsLengthsOfDataStructures(result); return result; } } public void Save(ssortingng fileName) { using (Stream stream = File.Create(fileName)) { new BinaryFormatter().Serialize(stream, this); } } public void OnDeserialization(object sender) { TestsLengthsOfDataStructures(this); } private static void TestsLengthsOfDataStructures(Data data) { Debug.Assert(data.List.Count == 2, "List"); Debug.Assert(data.Dictionary.Count == 2, "Dictionary"); } } 

Je peux reproduire le problème. J’ai jeté un coup d’œil à Google et découvert ceci: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94265 bien que je ne sois pas sûr que ce soit exactement le même problème, il semble assez similaire.

MODIFIER:

Je pense que l’ajout de ce code peut avoir résolu le problème?

  public void OnDeserialization(object sender) { this.Dictionary.OnDeserialization(sender); } 

Pas le temps de tester de manière exhaustive, et je veux battre Marc à la réponse 😉

Oui, vous avez découvert un problème bizarre dans la désérialisation du Dictionary . Vous pouvez le contourner en appelant manuellement la méthode OnDeserialization() du dictionnaire:

 public void OnDeserialization(object sender) { Dictionary.OnDeserialization(this); TestsLengthsOfDataStructures(this); } 

Incidemment, vous pouvez également utiliser l’atsortingbut [OnDeserialized] plutôt que IDeserializationCallback :

 [OnDeserialized] public void OnDeserialization(StreamingContext context) { Dictionary.OnDeserialization(this); TestsLengthsOfDataStructures(this); } 

Intéressant … pour info, je l’ai essayé avec l’approche basée sur les atsortingbuts (ci-dessous), et il se comporte de la même façon … très curieux! Je ne peux pas l’expliquer – je réponds simplement pour confirmer la reproduction, et pour mentionner le comportement [OnDeserialized] :

 [OnDeserialized] // note still not added yet... private void OnDeserialized(StreamingContext context) {...} 

Edit – trouvé le problème “connect” ici . Essayez d’append à votre rappel:

 Dictionary.OnDeserialization(this);