2013-08-21 19 views
6

Ich habe Probleme beim Deserialisieren einer Liste von Objekten. Ich kann nur ein Objekt in ein Objekt serialisieren, bekomme aber die Liste nicht. Ich bekomme keinen Fehler es gibt nur eine leere Liste zurück. Dies ist der XML, die zurückgegeben wird:Probleme Deserialisierung Liste der Objekte

<locations> 
    <location locationtype="building" locationtypeid="1"> 
    <id>1</id> 
    <name>Building Name</name> 
    <description>Description of Building</description> 
    </location> 
</locations> 

Dies ist die Klasse ich habe, und ich bin Deserialisieren in der GetAll Methode:

[Serializable()] 
[XmlRoot("location")] 
public class Building 
{ 
    private string method; 

    [XmlElement("id")] 
    public int LocationID { get; set; } 
    [XmlElement("name")] 
    public string Name { get; set; } 
    [XmlElement("description")] 
    public string Description { get; set; } 
    [XmlElement("mubuildingid")] 
    public string MUBuildingID { get; set; } 

    public List<Building> GetAll() 
    { 
     var listBuildings = new List<Building>(); 
     var building = new Building(); 
     var request = WebRequest.Create(method) as HttpWebRequest; 
     var response = request.GetResponse() as HttpWebResponse; 

     var streamReader = new StreamReader(response.GetResponseStream()); 
     TextReader reader = streamReader; 
     var serializer = new XmlSerializer(typeof(List<Building>), 
      new XmlRootAttribute() { ElementName = "locations" }); 
     listBuildings = (List<Building>)serializer.Deserialize(reader); 

     return listBuildings; 
    } 
} 
+0

Was Der Fehler bekommst du? –

+0

Welche Liste sehen Sie nicht serialisiert? Wenn es die 'GetAll()' Methode ist, dann ist das, weil Serialisierer nicht (gut, möglicherweise selten, ich denke) im Geschäft der aufrufenden Klassenmethoden sind. Sie sind dabei, die Eigenschaften eines Objekts zu erhalten. – 48klocs

+0

Ich erhalte keinen Fehler, es wird nur eine leere Liste zurückgegeben. Ich versuche nicht, die GetAll-Methode zu serialisieren, ich benutze die Get All-Methode, um aus einem Webdienst zu deserialisieren und dieses Gebäudeobjekt zu füllen. –

Antwort

6

starten:

[XmlRoot("locations")] 
public class BuildingList 
{ 
    public BuildingList() {Items = new List<Building>();} 
    [XmlElement("location")] 
    public List<Building> Items {get;set;} 
} 

Dann deserialisieren die ganzes BuildingList-Objekt.

var xmlSerializer = new XmlSerializer(typeof(BuildingList)); 
var list = (BuildingList)xmlSerializer.Deserialize(xml); 
+0

Zu Ihrer Information, wenn Sie die Attribute deserialisieren müssen (z. B. "locationtype" usw.), können Sie auch die entsprechende Eigenschaft mit 'XmlAttribute' dekorieren. – ricovox

+0

Fehler Das Attribut 'XmlElement' ist für diesen Deklarationstyp nicht gültig. Es ist nur gültig für die Deklarationen "property, indexer, field, param, return". –

+0

Ok, ich denke ich sehe das Problem. Ich werde meine Antwort aktualisieren. – ricovox

2

Nicht sicher, wie Gebäude mit der Position entspricht, die Sie in Ihrem xml, aber mir macht es mehr Sinn, wenn sie in äquivalenter Weise genannt sind. Statt eine Liste des mit einem LocationList verwenden, und es wird:

[Serializable()] 
[XmlRoot("locations")] 
public class LocationCollection{ 
    [XmlElement("location")] 
    public Location[] Locations {get;set;} 
} 

[Serializable()] 
[XmlRoot("location")] 
public class Location 
{  
    [XmlElement("id")] 
    public int LocationID { get; set; } 
    [XmlAttribute("locationtype")] 
    public string LocationType {get;set;} 
    [XmlElement("name")] 
    public string Name { get; set; } 
    [XmlElement("description")] 
    public string Description { get; set; } 
    [XmlElement("mubuildingid")] 
    public string MUBuildingID { get; set; }  
} 

können Sie dann deserialisieren wie folgt:

var request = WebRequest.Create(method) as HttpWebRequest; 
var response = request.GetResponse() as HttpWebResponse; 

var streamReader = new StreamReader(response.GetResponseStream()); 
TextReader reader = streamReader; 
var serializer = new XmlSerializer(typeof(LocationCollection), 
    new XmlRootAttribute() { ElementName = "locations" }); 
var listBuildings = (LocationCollection)serializer.Deserialize(reader); 

return listBuildings; 
+0

Gebäude ist nur eine Art von LocationType und diese spezifische Anwendung benötigt nur Gebäude, also hat sie ein Gebäudeobjekt, das sie in der Anwendung benutzt, die durch den Webservice gefüllt wird. Ich habe versucht, eine andere Klasse nur für Collections zu erstellen, da die Rückgabe in einer Methode oder in einer statischen Methode innerhalb des Objekts alles im Objekt lokalisierte. –

+1

IMHO, ein DTO, der intern einen Webservice aufruft, scheint mir eine wirklich schlechte Idee zu sein. Außerdem können Sie die LocationCollection immer noch intern halten und dann einfach listBuildings.Locations zurückgeben. Dies ist Location [] – DavidN

+0

Wie unterscheidet sich das von dem, was ich gepostet habe? Sie wechselten nur von einer Liste zu einem Array, und das OP forderte eine Liste ricovox

3

Ich weiß, das ist eine alte (er) Frage, aber ich kämpfte mit diesem heute, und eine Antwort gefunden, die keine Kapselung erfordert.

Annahme 1: Sie haben die Kontrolle über die Quelle Xml und wie es aufgebaut ist.

Annahme 2: Sie versuchen, die XML-Daten direkt in ein List<T> Objekt

  1. Sie das Root-Element als ArrayOfxxx im XML-Name muss serialise wobei xxx der Name der Klasse (oder den Namen angegeben in XmlType (siehe 2.))
  2. Wenn Sie wünschen, dass Ihre XML-Elemente einen anderen Namen als die Klasse haben, sollten Sie XmlType für die Klasse verwenden.

NB: Wenn Ihr Typ Name (oder Klassenname) mit einem Kleinbuchstaben beginnt, sollten Sie das erste Zeichen in Großbuchstaben umwandeln.

Beispiel 1 - Ohne XmlType

class Program 
{ 
    static void Main(string[] args) 
    { 
     //String containing the xml array of items. 
     string xml = 
@"<ArrayOfItem> 
    <Item> 
     <Name>John Doe</Name> 
    </Item> 
    <Item> 
     <Name>Martha Stewart</Name> 
    </Item> 
</ArrayOfItem>"; 


     List<Item> items = null; 
     using (var mem = new MemoryStream(Encoding.Default.GetBytes(xml))) 
     using (var stream = new StreamReader(mem)) 
     { 
      var ser = new XmlSerializer(typeof(List<Item>)); //Deserialising to List<Item> 
      items = (List<Item>)ser.Deserialize(stream); 
     } 

     if (items != null) 
     { 
      items.ForEach(I => Console.WriteLine(I.Name)); 
     } 
     else 
      Console.WriteLine("No Items Deserialised"); 

    } 
} 

public class Item 
{ 
    public string Name { get; set; } 
} 

Beispiel 2 - Mit XmlType

class Program 
{ 
    static void Main(string[] args) 
    { 
     //String containing the xml array of items. 
     //Note the Array Name, and the Title case on stq. 
     string xml = 
@"<ArrayOfStq> 
    <stq> 
     <Name>John Doe</Name> 
    </stq> 
    <stq> 
     <Name>Martha Stewart</Name> 
    </stq> 
</ArrayOfStq>"; 


     List<Item> items = null; 
     using (var mem = new MemoryStream(Encoding.Default.GetBytes(xml))) 
     using (var stream = new StreamReader(mem)) 
     { 
      var ser = new XmlSerializer(typeof(List<Item>)); //Deserialising to List<Item> 
      items = (List<Item>)ser.Deserialize(stream); 
     } 

     if (items != null) 
     { 
      items.ForEach(I => Console.WriteLine(I.Name)); 
     } 
     else 
      Console.WriteLine("No Items Deserialised"); 

    } 
} 

[XmlType("stq")] 
public class Item 
{ 
    public string Name { get; set; } 
} 
-1

Verwenden [XMLArray] abhol Eigenschaften.

0

Ich weiß, alte Frage, aber stieß auf sie, wenn ein ähnliches Problem konfrontiert. Aufbauend auf @ ricovox Antwort und in Zusammenhang mit der Frage des OP ist dies das Modell, das ich würde seine xml serialisiert verwenden:

[Serializable, XmlRoot("locations")] 
public class BuildingList 
{ 
    [XmlArrayItem("location", typeof(Building))] 
    public List<Building> locations { get; set; } 
} 

[Serializable] 
public class Building 
{ 
    public int LocationID { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public string MUBuildingID { get; set; } 

    public List<Building> GetAll() 
    { 
     ... 
    } 
} 

Die OP Fehler war das Listenelement als Wurzel erstellen

Verwandte Themen