2012-02-07 13 views
6

To ładuje zestaw wartości z pliku XML i umieszcza je w klasie w celu przechowywania. Próbuję dowiedzieć się, jak wyświetlić wartości w postaci listy, dzięki czemu można umieścić je w polu listy.Wyprowadzanie klasy przechowywanych wartości do listy

Pomyślałem, że będzie łatwy sposób, taki jak metoda .ToList() lub możliwość przeglądania za pośrednictwem ciągów w klasie (brak publicznego wzorca). Udało mi się odkryć, że Foreach ukrywa część złożoności, ale nie od robienia tego, co chcę.

Szukałem w Internecie z bezskutecznie (brakuje prawidłowej terminologii może), niestety zostawiłem moje książki C# odniesienia w pracy:/

Czy doceniam wskaźnik we właściwym kierunku, Dzięki.

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.IO; 
using System.Xml; 

namespace ThereIsOnlyRules 
{ 
public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 
     try 
     { 
      listBox1.Items.Clear(); 

      string path = "characterXML.xml"; 
      FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
      System.Xml.XmlDocument CXML = new System.Xml.XmlDocument(); 

      CXML.Load(fs); 

      //Get the number of elements 
      XmlNodeList elemList = CXML.GetElementsByTagName("unit"); 

      //foreach (var element in elemList) 
      //{ 
      // listBox1.Items.Add(element); 
      //} 

      for (int i = 0; i < elemList.Count; i++) 
      { 
       UnitAttributes attributes = new UnitAttributes(); 

       attributes.army = elemList[i].Attributes["army"].Value; 
       attributes.category = elemList[i].Attributes["category"].Value; 
       attributes.type = elemList[i].Attributes["type"].Value; 
       attributes.composition = elemList[i].Attributes["composition"].Value; 
       attributes.WS = elemList[i].Attributes["WS"].Value; 
       attributes.BS = elemList[i].Attributes["BS"].Value; 
       attributes.T = elemList[i].Attributes["T"].Value; 
       attributes.W = elemList[i].Attributes["W"].Value; 
       attributes.I = elemList[i].Attributes["I"].Value; 
       attributes.A = elemList[i].Attributes["A"].Value; 
       attributes.LD = elemList[i].Attributes["LD"].Value; 
       attributes.save = elemList[i].Attributes["Save"].Value; 
       attributes.armour = elemList[i].Attributes["armour"].Value; 
       attributes.weapons = elemList[i].Attributes["weapons"].Value; 
       attributes.specialrules = elemList[i].Attributes["specialrules"].Value; 
       attributes.transport = elemList[i].Attributes["transport"].Value; 
       attributes.options = elemList[i].Attributes["options"].Value; 

       //foreach (string item in attributes) 
       //{ 

        //unit.Add(item); 
       //} 
       //listBox1.Items.AddRange(attributes) 

      } 

      //Close the filestream 
      fs.Close(); 
     } 
     catch (Exception ex) 
     { 

     } 
    } 
} 
} 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ThereIsOnlyRules 
{ 
class UnitAttributes 
{ 
    public string army { get; set; } 
    public string category { get; set; } 
    public string type { get; set; } 
    public string composition { get; set; } 
    public string WS { get; set; } 
    public string BS { get; set; } 
    public string T { get; set; } 
    public string W { get; set; } 
    public string I { get; set; } 
    public string A { get; set; } 
    public string LD { get; set; } 
    public string save { get; set; } 
    public string armour { get; set; } 
    public string weapons { get; set; } 
    public string specialrules { get; set; } 
    public string transport { get; set; } 
    public string options { get; set; } 
    } 
} 

<?xml version="1.0"?> 
<config> 
<unit 
army="Tyranids" 
category="Troops" 
type="Infantry" 
composition="10-30" 
WS="3" 
BS="3" 
T="3" 
W="1" 
I="4" 
A="1" 
LD="6" 
Save="6+" 
armour="Chitin" 
weapons="Claws and Teeth, Fleshborer" 
specialrules="Instictive Behaviour - Lurk, Move Through Cover" 
transport="If the brood consists of 20 models or less, it may take a Mycetic Spore." 
options="Strangleweb, Spinefists, Spike rifle, Devourer, Adrenal Glands, Toxin Sacs" 
> 
Termagant Brood 
</unit> 
<unit 
army="Tyranids" 
category="Troops" 
type="Infantry" 
composition="10-30" 
WS="3" 
BS="3" 
T="3" 
W="1" 
I="5" 
A="2" 
LD="6" 
Save="6+" 
armour="Chitin" 
weapons="Scything Talons" 
specialrules="Instictive Behaviour - Feed, Bounding Leap, Fleet, Move Through Cover" 
transport="If the brood consists of 20 models or less, it may take a Mycetic Spore." 
options="Adrenal Glands, Toxin Sacs" 
> 
Hormagaunt Brood 
</unit> 
</config> 
+1

'XmlNodeList' implementuje' IEnumerable', więc twoje 'foreach' powinno działać. – svick

Odpowiedz

3

Czy członkowie pól lub właściwości klasy? Tak czy inaczej, trochę refleksji i Linq powinien umożliwić wyliczenie za pośrednictwem elementów danych klasy, po uwodnieniu jej instancji z pliku XML.

var fieldDictionary = 
    (from f in typeof(UnitAttributes).GetFields() 
    select new {Name = f.Name, Value = (string)(f.GetValue(attributes))}) 
    .ToDictionary(x=>x.Name, x=>x.Value); 

fieldDictionary jest teraz Dictionary<string, string> (który jest IEnumerable<KeyValuePair<string, string>>), które powinny nadawać się do ładowania w listą.

Bądź poinformowany; odbicie jest powolne. Znacznie lepiej byłoby zmodyfikować lub rozszerzyć klasę UnitAttributes, aby zaimplementować IEnumerable (prawdopodobnie Tuple, może KeyValuePair). Umożliwiłoby to również wyliczenie właściwości instancji klasy w dokładnie takiej kolejności, jakiej chcesz, zamiast kolejności, w której są zdefiniowane, lub za pomocą innych danych FieldInfo/PropertyInfo, takich jak nazwa pola.

Należy również pamiętać, że pole nie jest własnością i odwrotnie. Jeśli masz mieszankę właściwości i pól publicznych na swojej klasie, bardzo zalecałbym standaryzację jednej lub drugiej; w przeciwnym razie będziesz musiał podać ZOBACZ listę właściwości i listę pól, używając dwóch z powyższych instrukcji Linq (kosztem około dwukrotnie więcej czasu pracy), i nie będzie szansy, że będą one zdefiniowane przez użytkownika zamówienie.

2

Zaoszczędzisz dużo czasu i wysiłku, jeśli użyjesz standardowego serializatora, takiego jak XmlSerializer do obsługi konwersji obiektów do/z ciągów. Nie musisz pisać tego typu kodu od zera.

+0

Zgadzam się, ale myślę, że sedno pytania polega na tym, jak wyliczyć dane w postaci obiektu, a nie XML. – KeithS

+0

Wciąż doceniam to, że mi powiedziano, że po prostu czytałem coś podobnego w innym miejscu. – Amicable

Powiązane problemy