2009-05-30 2 views
7

Wie ich es verstehe, muss ich ein neues Mitglied in einer neueren Version meiner Klasse mit dem Attribut [OptionalField] schmücken, wenn ich eine ältere Version meiner Klasse deserialize, die dieses neuere Mitglied fehlt.Was ist mit dem Attribut [OptionalField]?

Der folgende Code löst jedoch keine Ausnahme aus, während die InnerTranslator-Eigenschaft nach dem Serialisieren der Klasse hinzugefügt wurde. Ich überprüfe, ob die Eigenschaft in der onDeserialization-Methode null ist (was bestätigt, dass sie nicht serialisiert wurde), aber ich hätte erwartet, dass der Code deswegen eine Ausnahme auslöst. Ist das [OptionalField] Attribut selbst optional?

class Program 
{ 
    static void Main(string[] args) 
    { 
     var listcol = new SortedList<string,string> 
     { 
      {"Estados Unidos", "United States"}, 
      {"Canadá", "Canada"}, 
      {"España", "Spain"} 
     }; 
     var translator = new CountryTranslator(listcol); 
     using (var file_stream=new FileStream("translator.bin",FileMode.Open)) 
     { 
      var formatter = new BinaryFormatter(); 
      translator = formatter.Deserialize(file_stream) as CountryTranslator; 
      file_stream.Close(); 
     } 
     Console.ReadLine(); 
    } 
} 

[Serializable] 
internal class CountryTranslator:IDeserializationCallback 
{ 
    public int Count { get; set; } 

    public CountryTranslator(SortedList<string,string> sorted_list) 
    { 
     this.country_list = sorted_list; 
     inner_translator = new List<string> {"one", "two"}; 
    } 
    //[OptionalField] 
    private List<string> inner_translator; 
    public List<string> InnerTranslator 
    { 
     get { return inner_translator; } 
     set { inner_translator = value; } 
    } 

    private SortedList<string, string> country_list; 

    public void OnDeserialization(object sender) 
    { 
     Debug.Assert(inner_translator == null); 
     Count=country_list.Count; 
    } 
} 
+0

Ich habe gerade herausgefunden, dass der SOAP-Formatierer eine Ausnahme auslöst, wenn der inner_translator nicht mit dem [OptionalField] -Attribut – Dabblernl

Antwort

8

BinaryFormatter ist, am besten Mal, sehr spröde, wenn Sie die Dinge ändern. Nicht zuletzt gibt es große Probleme mit automatically implemented properties, obfuscaction, Umbenennung, starke Benennung, etc.

Wie ich mich erinnere, einige der Regeln über [OptionalField] geändert, kurz bevor es veröffentlicht wurde; Die versionstolerante Sache funktionierte nicht so einfach wie geplant, erwarte ich.

Mein Rat: Wenn Sie eine versionstolerante Serialisierung wünschen (d. H. Sie können sie heute serialisieren und mit der nächsten Version Ihrer App deserialisieren), dann verwenden Sie nicht BinaryFormatter; Dies ist (IMO) nur geeignet für die Weitergabe von Daten zwischen der gleichen Version (Remoting, AppDomain s, etc).

Für die Arbeit zwischen Versionen, empfehle ich vertragsbasierte Serialisierung; Dinge wie XmlSerializer und DataContractSerializer (.NET 3.0), oder für binäre - protobuf-net oder ähnliche Tools. Alle diese sind viel besser bei der Version Toleranz (in der Tat, Sie müssen es nicht einmal in das gleiche deserialize Type); Außerdem können sie zwischen Plattformen verwendet werden - so können Sie in .NET serialisieren und in java/C++/deserialisieren.

+0

Nicht genau die Antwort, die ich suchte, aber ich habe den DataContractSerializer ausschließlich seit verwendet Du hast es in diesem Post angepriesen. Also danke noch mal ;-) – Dabblernl

+0

Würden Sie jemals [OptionalField] für Werttypen wie Booleans oder Integers verwenden? Oder ist dieses Attribut nur für Referenztypen wie in der OP-Frage relevant? –