2010-12-29 5 views
1

Ich konnte keine Frage zu meinem spezifischen Problem finden.Verwendung von XmlSerializer zum Deserialisieren einer einfachen Auflistung in eine Instanz der Liste <string>

Was ich versuche, ist eine Liste von Xml-Knoten zu nehmen und sie direkt zu einer Liste zu deserialisieren, ohne eine Klasse mit Attributen erstellen zu müssen.

So ist die xml (myconfig.xml) würde wie folgt aussehen ...

<collection> 
    <item>item1</item> 
    <item>item2</item> 
    <item>item3</item> 
    <item>etc...</item> 
</collection> 

Am Ende würde ich eine Liste der Elemente als Strings mögen.

Der Code würde so aussehen.

Ich bin nicht 100% zuversichtlich, dass dies möglich ist, aber ich schätze, es sollte sein. Jede Hilfe würde sehr geschätzt werden.

+0

Vielen Dank für Ihre Korrektur abatishchev – Nicholas

Antwort

3

Sind Sie mit der Idee eines Serialisierers verheiratet? Wenn nicht, können Sie Linq-to-XML ausprobieren. (.NET 3.5, C# 3 [und höher])

Basierend auf Ihrem bereitgestellten XML-Dateiformat ist dies der einfache Code.

+0

kühle Alternative.Ich denke jedoch, dass der Vorteil des Serialisierers darin liegt, dass ich ihn auch zum Speichern meiner Konfiguration verwenden kann, wenn sich die Sammlung ändert. Wie auch immer, Ihr Beispiel ist hilfreich für mich. – Nicholas

+1

Erkunden Sie es. Sie können auch Linq-to-XML verwenden, um Ihre XML-Dateien zu schreiben. Es ist ein nettes Werkzeug. –

+0

Ich werde das untersuchen, aber an diesem Punkt versuche ich, Details mit dem XmlSerializer herauszufinden. Für mich ist es interessant zu wissen, dass .Net ArrayOfString als Wurzelknoten für eine Sammlung und den Typ als Elementnamen verwendet. Sicherlich ist Ihr Beispiel am besten, wenn Sie eine einfache XML-Datei laden und lesen, aber meine Frage konzentriert sich derzeit auf das Verhalten des XmlSerializers, da ich mehr oder weniger ausführlich bei der Definition komplexerer Dateien für Serialisierung und Deserialisierung sein kann. Wenn Sie nicht sagen, dass Linq-to-XML den XmlSerializer vollständig ersetzen kann ...? – Nicholas

1

Ok, interessanterweise habe ich vielleicht die halbe Antwort gefunden, indem ich eine bestehende Liste serialisiert habe.

Das Ergebnis habe ich wird wie folgt ...

Dieser folgenden Code:

List<string> things = new List<string> { "thing1", "thing2" }; 
XmlSerializer serializer = new XmlSerializer(typeof(List<string>), overrides); 
using (TextWriter textWriter = new StreamWriter("things.xml")) 
{ 
    serializer.Serialize(textWriter, things); 
} 

gibt ein Ergebnis von:

<?xml version="1.0" encoding="utf-8"?> 
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <string>thing1</string> 
    <string>thing2</string> 
</ArrayOfString> 

I den Wurzelknoten außer Kraft setzen kann eine durch Hindurchleiten XmlAttributeOverrides-Instanz zum zweiten Parameter des XmlSerializer-Konstruktors. Es wird so erstellt:

XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 
XmlAttributes attributes = new XmlAttributes { XmlRoot = new XmlRootAttribute("collection") }; 
overrides.Add(typeof(List<string>), attributes); 

Dies wird "ArrayOfString" in "Sammlung" ändern. Ich habe immer noch nicht herausgefunden, wie man den Namen des String-Elements steuert.

1

Um Listenelementnamen mithilfe von XmlSerializer anzupassen, müssen Sie die Liste umbrechen.

[XmlRoot(Namespace="", ElementName="collection")] 
public class ConfigWrapper 
{ 
    [XmlElement("item")] 
    public List<string> Items{ get; set;} 
} 

Verbrauch:

var itemsList = new List<string>{"item1", "item2", "item3"}; 
    var cfgIn = new ConfigWrapper{ Items = itemsList }; 
    var xs = new XmlSerializer(typeof(ConfigWrapper)); 
    string fileContent = null; 

    using (var sw = new StringWriter()) 
    { 
     xs.Serialize(sw, cfgIn); 
     fileContent = sw.ToString(); 
     Console.WriteLine (fileContent); 
    } 

    ConfigWrapper cfgOut = null; 
    using (var sr = new StringReader(fileContent)) 
    { 
     cfgOut = xs.Deserialize(sr) as ConfigWrapper; 
     // cfgOut.Dump(); //view in LinqPad 
     if(cfgOut != null) 
      // yields 'item2' 
      Console.WriteLine (cfgOut.Items[1]); 
    } 

Ausgang:

// fileContent: 
<?xml version="1.0" encoding="utf-16"?> 
<collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <item>item1</item> 
    <item>item2</item> 
    <item>item3</item> 
</collection> 

Wenn Sie die Liste nicht wickeln wollen, wird die DataContractSerializer können Sie benutzerdefinierte Elemente nennen, wenn Sie es Unterklasse :

[CollectionDataContract(Name = "collection", ItemName = "item", Namespace = "")] 
public class ConfigWrapper : List<string> 
{ 
    public ConfigWrapper() : base() { } 
    public ConfigWrapper(IEnumerable<string> items) : base(items) { } 
    public ConfigWrapper(int capacity) : base(capacity) { } 
} 

Verbrauch und Leistung:

var cfgIn = new ConfigWrapper{ "item1", "item2", "item3" }; 
    var ds = new DataContractSerializer(typeof(ConfigWrapper)); 
    string fileContent = null; 

    using (var ms = new MemoryStream()) 
    { 
     ds.WriteObject(ms, cfgIn); 
     fileContent = Encoding.UTF8.GetString(ms.ToArray()); 
     Console.WriteLine (fileContent); 
    } 
    // yields: <collection xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><item>item1</item><item>item2</item><item>item3</item></collection> 

    ConfigWrapper cfgOut = null; 
    using (var sr = new StringReader(fileContent)) 
    { 
     using(var xr = XmlReader.Create(sr)) 
     { 
      cfgOut = ds.ReadObject(xr) as ConfigWrapper; 
      // cfgOut.Dump(); //view in LinqPad 
      if(cfgOut != null) 
       // yields 'item2' 
       Console.WriteLine (cfgOut[1]); 
     } 
    } 
Verwandte Themen