2016-06-19 4 views
1

Also habe ich eine XML-Datei, die ich versuche, in eine generische Liste zu deserialisieren, aber egal was ich tue, bleibt die Liste leer. Ich habe die ersten ~ 10 Stack Overflow Fragen geworfen, die dazu gekommen sind, aber ich habe es noch nicht herausgefunden.statische Xml Deserialisierung in eine generische Liste in C# funktioniert nicht

Wenn das Programm startet, rufe ich FishContainer.Load(), liest der Datei-Reader die Datei einwandfrei, aber nichts geht in die Liste.

XML-Datei

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<FishContainer> 
    <Fishies> 
     <Fish Name = "test"> 
      <WaterType>salt</WaterType> 
      <Price>1</Price> 
      <Size>1</Size> 
      <Aggression>1</Aggression> 
     </Fish> 
     <Fish Name = "test2"> 
      <WaterType>fresh</WaterType> 
      <Price>12</Price> 
      <Size>12</Size> 
      <Aggression>12</Aggression> 
     </Fish> 
    </Fishies> 
</FishContainer> 

Fisch Container

using UnityEngine; 
using System.Collections.Generic; 
using System.Xml.Serialization; 
using System.IO; 

public static class FishContainer { 
[XmlArray("Fishies"), XmlArrayItem("Fish")] 
public static List<FishData> fishs = new List<FishData>(); 

public static void Load() { 
    TextAsset _xml = Resources.Load<TextAsset>("fishdata"); 
    XmlSerializer serializer = new XmlSerializer(typeof(List<FishData>), new XmlRootAttribute("FishContainer")); 
    StringReader reader = new StringReader(_xml.text); 
    fishs = (List<FishData>)serializer.Deserialize(reader); 
    reader.Close(); 

    Debug.Log(fishs.Count); 
} 

public static FishData GetFishAttributeByName(string name) { 
    foreach(FishData f in fishs) { 
     if(f.Name.Equals(name)) 
      return f; 
    } 
    return null; //throw 
} 
} 

Fisch Daten

using System.Xml; 
using System.Xml.Serialization; 

public class FishData { 
[XmlAttribute("Name")] public string Name; 
[XmlElement("WaterType")] public string WaterType; 
[XmlElement("Price")] public int Price; 
[XmlElement("Size")] public int Size; 
[XmlElement("Aggression")] public int Aggression; 

public override string ToString() { 
    return Name + " " + WaterType + " " + Price + " " + Size + " " + Aggression; 
} 
} 

Antwort

1

Das Problem ist, du bist deserial ist der Typ List<FishData>, aber das ist nicht, was Ihre XML-Datei auf der obersten Ebene enthält, es ist eine FishContainer, die wiederum eine Eigenschaft von List<FishData> darin hat.

Sie können auch nicht zu einer statischen Eigenschaft oder Klasse deserialisieren, daher müssen Sie die statischen Modifikatoren in FishContainer für die Klasse und die Eigenschaft mindestens entfernen. Hier ist, wie ich würde FishContainer korrigieren:

public class FishContainer 
{ 
    [XmlArray("Fishies"), XmlArrayItem("Fish")] 
    public List<FishData> Fishes { get; set; } 

    public static FishContainer Load(string xml) 
    { 
     XmlSerializer serializer = new XmlSerializer(typeof(FishContainer), new XmlRootAttribute("FishContainer")); 
     using (StringReader reader = new StringReader(xml)) 
      return (FishContainer)serializer.Deserialize(reader); 
    } 

    public FishData GetFishAttributeByName(string name) 
    { 
     return Fishes 
       .SingleOrDefault(fish => fish.Name.Equals(name)); 
    } 
} 

In der Regel persönlich versuche ich nur static Methoden oder Eigenschaften zu verwenden, wenn sie nicht den Zustand etwas ändern oder halten. Sie können dies wie folgt nennen;

var fishContainer = FishContainer.Load(_xml); 
Console.WriteLine("I have {0} fishes", fishContainer.Fishes.Count); 

EDIT: aber, wie Sie es wollen statisch mit nur einer einzigen Instanz von FishContainer zur Verfügung stehen, können Sie etwas tun könnte:

public class FishContainer 
{ 
    private static FishContainer _instance; 

    [XmlArray("Fishies"), XmlArrayItem("Fish")] 
    public List<FishData> Fishes { get; set; } 

    public static void Load(string xml) 
    { 
     XmlSerializer serializer = new XmlSerializer(typeof(FishContainer), new XmlRootAttribute("FishContainer")); 
     using (StringReader reader = new StringReader(xml)) 
      _instance = (FishContainer)serializer.Deserialize(reader); 
    } 

    public static FishData GetFishAttributeByName(string name) 
    { 
     if (_instance == null) 
      throw new InvalidOperationException("FishContainer has not been loaded"); 

     return 
      _instance 
      .Fishes 
      .SingleOrDefault(fish => fish.Name.Equals(name)); 
    } 
} 

.. und rufen Sie wie folgt aus:

FishContainer.Load(_xml); 
var someFish = FishContainer.GetFishAttributeByName("test"); 
+0

Vielen Dank dafür. Ich hatte es ähnlich wie früher, aber in meinem Programm werde ich die FishData-Liste von mehreren Objekten aufrufen. Ich versuche den besten Weg herauszufinden, dies zu tun. Idealerweise möchte ich "FishContainer.GetFishByName (" blah ") sagen, aber jetzt muss ich nachverfolgen, welches Objekt die Liste überhaupt gemacht hat. – user318798

+0

@ user318798, wenn Sie es statisch verfügbar benötigen und es immer nur eine einzige Instanz von 'FishContainer' gibt, die Sie verfügbar haben, siehe letzte Änderung. – steve16351

+0

Wow! Genau danach suche ich. Ich danke dir sehr! Auch nette Berührung mit dem Lambda-Ausdruck, daran habe ich gar nicht gedacht. – user318798