2008-12-18 6 views
18

Ich habe eine einfache Klasse, die von Collection erbt und fügt ein paar Eigenschaften hinzu. Ich muss diese Klasse in XML serialisieren, aber der XMLSerializer ignoriert meine zusätzlichen Eigenschaften.XmlSerialize eine benutzerdefinierte Sammlung mit einem Attribut

Ich nehme an, dies liegt an der speziellen Behandlung, die XMLSerializer ICollection und IEnumerable Objekte gibt. Was ist der beste Weg?

Hier ist ein Beispielcode:

using System.Collections.ObjectModel; 
using System.IO; 
using System.Xml.Serialization; 

namespace SerialiseCollection 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var c = new MyCollection(); 
      c.Add("Hello"); 
      c.Add("Goodbye"); 

      var serializer = new XmlSerializer(typeof(MyCollection)); 
      using (var writer = new StreamWriter("test.xml")) 
       serializer.Serialize(writer, c); 
     } 
    } 

    [XmlRoot("MyCollection")] 
    public class MyCollection : Collection<string> 
    { 
     [XmlAttribute()] 
     public string MyAttribute { get; set; } 

     public MyCollection() 
     { 
      this.MyAttribute = "SerializeThis"; 
     } 
    } 
} 

Das gibt das folgende XML (beachten Sie MyAttribute ist im MyCollection Element fehlt):

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

Was ich wollen

<MyCollection MyAttribute="SerializeThis" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <string>Hello</string> 
    <string>Goodbye</string> 
</MyCollection> 
ist

Irgendwelche Ideen? Je einfacher, desto besser. Vielen Dank.

Antwort

13

Sammlungen sind im Allgemeinen keine guten Orte für zusätzliche Eigenschaften. Sowohl bei der Serialisierung als auch bei der Datenbindung werden sie ignoriert, wenn das Objekt wie eine Sammlung aussieht (IList, IEnumerable, usw. - je nach Szenario).

Wenn es mir war, würde ich die Sammlung kapseln - also

[Serializable] 
public class MyCollectionWrapper { 
    [XmlAttribute] 
    public string SomeProp {get;set;} // custom props etc 
    [XmlAttribute] 
    public int SomeOtherProp {get;set;} // custom props etc 
    public Collection<string> Items {get;set;} // the items 
} 

Die andere Option IXmlSerializable (ziemlich viel Arbeit) zu implementieren ist, aber das wird noch nicht für Datenbindung etc arbeiten Grundsätzlich ist dies nicht die erwartete Verwendung.

0

Ich habe mit dem gleichen Problem kämpfen Romaroo ist (will Eigenschaften der XML-Serialisierung einer Klasse hinzufügen, die ICollection implementiert). Ich habe keine Möglichkeit gefunden, Eigenschaften in der Collection-Klasse verfügbar zu machen. Ich habe sogar versucht, das XmlAttribute-Tag zu verwenden und meine Eigenschaften als Attribute des Root-Knotens erscheinen zu lassen, aber auch kein Glück. Ich war jedoch in der Lage, das XmlRoot-Tag in meiner Klasse zu verwenden, um es von "ArrayOf ..." umzubenennen. Hier sind einige Hinweise, falls Sie interessiert sind:

+0

Siehe meine Lösung, könnten Sie es interessant finden. – toddmo

12

Wenn Sie kapseln, wie Marc GRA schon sagt, der Anfang dieses Beitrags wird erklärt, wie Lassen Sie Ihr XML genau so aussehen, wie Sie es beschreiben.

http://blogs.msdn.com/youssefm/archive/2009/06/12/customizing-the-xml-for-collections-with-xmlserializer-and-datacontractserializer.aspx

Das heißt, statt dies:

<MyCollection MyAttribute="SerializeThis" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Items> 
    <string>Hello</string> 
    <string>Goodbye</string> 
    <Items> 
</MyCollection> 

Sie können dieses:

<MyCollection MyAttribute="SerializeThis" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">  
    <string>Hello</string> 
    <string>Goodbye</string> 
</MyCollection> 
+0

@ neilwhitaker1: Ich habe diese Antwort upvoted, aber es wäre noch besser, wenn Sie die Technik in der Antwort beschrieben, anstatt uns dazu zu bringen, den Blogpost zu lesen. Sie können immer noch auf den Beitrag verweisen. –

+1

Der Blogpost beantwortet die Frage sehr gut mit einem angemessenen Detaillierungsgrad und die Antwort ist innerhalb des Blogposts leicht zu finden. Ich denke, dass die Verknüpfung mit dem Blog in diesem Fall vorzuziehen ist. – AndrewS

0

Wie Neil Whitaker schlägt vor, und im Falle seiner Verbindung stirbt ..

eine innere Sammlung Erstellen Sie die Saiten zu speichern und das XmlElement Attribut gelten den Namen der Sammlung zu maskieren. Erzeugt die gleiche XML-Ausgabe, als ob MyCollection von Collection geerbt hätte, serialisiert aber auch Attribute für das übergeordnete Element.

[XmlRoot("MyCollection")] 
public class MyCollection 
{ 
    [XmlAttribute()] 
    public string MyAttribute { get; set; } 

    [XmlElement("string")] 
    public Collection<string> unserializedCollectionName { get; set; } 

    public MyCollection() 
    { 
     this.MyAttribute = "SerializeThis"; 
     this.unserializedCollectionName = new Collection<string>(); 
     this.unserializedCollectionName.Add("Hello"); 
     this.unserializedCollectionName.Add("Goodbye"); 
    } 
} 
Verwandte Themen