2009-01-19 5 views
16

Ich stieß auf ein, mindestens zu meinen Erwartungen, seltsames Verhalten in der binären Serialisierung von .NET.Merkwürdiges Verhalten der .NET-Binärserialisierung auf Wörterbuch <Key, Value>

Alle Elemente eines Dictionary, die geladen werden, werden nach der Rückruffunktion OnDeserialization zu ihrem übergeordneten Element hinzugefügt. Im Gegensatz dazu List ist der andere Weg. Dies kann im reellen Repository-Code wirklich störend sein, wenn Sie zum Beispiel einige Delegaten zu Wörterbuchelementen hinzufügen müssen. Bitte überprüfe den Beispielcode und beobachte die Behauptungen.

Ist es normales Verhalten?

[Serializable] 
public class Data : IDeserializationCallback 
{ 
    public List<string> List { get; set; } 

    public Dictionary<string, string> Dictionary { get; set; } 

    public Data() 
    { 
     Dictionary = new Dictionary<string, string> { { "hello", "hello" }, { "CU", "CU" } }; 
     List = new List<string> { "hello", "CU" }; 
    } 

    public static Data Load(string filename) 
    { 
     using (Stream stream = File.OpenRead(filename)) 
     { 
      Data result = (Data)new BinaryFormatter().Deserialize(stream); 
      TestsLengthsOfDataStructures(result); 

      return result; 
     } 
    } 

    public void Save(string 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"); 
    } 
} 
+0

Ich finde es schwer, die Antworten zu folgen, weil Ihre Objektinstanz hat denselben Namen wie die Klasse! Wie können Sie zwischen statischen und Member-Methoden unterscheiden? –

Antwort

8

Ich kann das Problem reproduzieren. Ich habe mich in Google umgesehen und folgendes gefunden: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94265 obwohl ich mir nicht sicher bin, ob es genau dasselbe Problem ist, scheint es ziemlich ähnlich zu sein.

EDIT:

Ich denke, dass dieser Code hinzufügt das Problem behoben haben kann?

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

keine Zeit erschöpfend zu testen, und ich möchte Marc auf die Antwort schlagen ;-)

+0

Ich denke, wir haben ihn ungefähr zur gleichen Zeit gefunden - vielleicht hast du mir einen Peitschenhieb gegeben, also +1 an dich ;-p –

+0

Eigentlich hat mein Beitrag das schon vor deinem Edit deutlich gemacht: ( –

+0

Und +1 an euch beide :-) – endian

4

Interessante ... für Info, habe ich versucht, es mit dem Attribut-basierten Ansatz (siehe unten), und es verhält sich die gleiche ... sehr gespannt! Ich kann es nicht erklären - ich antworte nur reproduzierten, um zu bestätigen, und das [OnDeserialized] Verhalten zu erwähnen:

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

Bearbeiten - gefunden „connect“ Ausgabe here. Versuchen Sie, zu Ihrem Rückruf hinzuzufügen:

Dictionary.OnDeserialization(this); 
+3

Nur um euch wissen zu lassen, dass der Link zwischenzeitlich gestorben ist. – Jeb

10

Ja, haben Sie eine lästige Marotte in Dictionary<TKey, TValue> Deserialisierung entdeckt. Sie können manuell drum herum kommen die OnDeserialization() Methode des Wörterbuch Aufruf:

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

Übrigens können Sie auch das [OnDeserialized] Attribut verwenden, anstatt IDeserializationCallback:

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

Keine leichte Absicht, Kent; +1 –

+0

Nur um ein Wort der Warnung hinzuzufügen: in meiner Umgebung führte der Versuch, zu einem deserialisierten Wörterbuch vor dem Aufruf seiner 'OnDeserialization' hinzuzufügen, zu einer' NullReferenceException', die aus dem Wörterbuch generiert wurde. – Nathan