2009-09-22 1 views
6

Czy istnieje sposób Take danego pliku XML i konwertowania (najlepiej przy użyciu C# Generics) go do betonu IEnumerable liście T, gdzie T jest moja beton klasyXML do IEnumerable <T>

Tak na przykład mogę mieć plik XML jak

<fruits> 
    <fruit> 
     <id>1</id> 
     <name>apple</name> 
    </fruit> 
    <fruit> 
     <id>2</id> 
     <name>orange</name> 
    </fruit> 
</fruits> 

i chciałbym zobaczyć listę owoc Przedmioty

gdzie ma właściwości takie jak

public class Fruit : IFruit 
{ 
    public string name; 
    public int id; 
} 

Przypuszczam, że muszę jakąś mapowania gdybym był w użyciu rodzajowych, jak chciałbym to działało idealnie dla interfejsu IFruit (nie wiem, jeśli to możliwe)

góry dzięki

Odpowiedz

9

Biorąc pod uwagę następujące rodzaje:

public interface IFruit 
{ 
    String name { get; set; } 
    Int32 id { get; set; } 
} 

public class Fruit : IFruit 
{ 
    public String name { get; set; } 
    public Int32 id { get; set; } 
} 

myślę, że można zrobić coś takiego:

static IEnumerable<T> GetSomeFruit<T>(String xml) 
     where T : IFruit, new() 
    { 
     return XElement.Parse(xml) 
      .Elements("fruit") 
      .Select(f => new T { 
       name = f.Element("name").Value, 
       id = Int32.Parse(f.Element("id").Value) 
      }); 
    } 

które można by nazwać tak:

IEnumerable<Fruit> fruit = GetSomeFruit<Fruit>(yourXml); 
+0

Podoba mi się to rozwiązanie i jest zgodne z możliwością serializacji XML. Jedynym komentarzem, jaki zrobiłbym, jest to, że konwencje .NET zwykle wymagają, aby pola publiczne (lub bardziej realistycznie, własności publiczne) zaczynały się od dużej litery, ale to była decyzja Harrisona, a nie wasza. –

+0

Fajnie. Aby zrobić to o krok dalej, wyobrażam sobie, że istnieje podklas dla każdego rodzaju owocu w przypadku ogólnej metody, takiej jak ta, która zwraca węzły owocowe odpowiadającego typu, tj. Jeśli T = pomarańczowy, wówczas zwracane są tylko te owoce, których nazwa to Pomarańczowa. . Metoda może porównać typof (T) .Name z nazwą owocu z xml i wykluczyć inne ... tylko moje 2 centy. –

+0

Jesteś geniuszem, uratowałeś moją pracę – Moons

0

Nie jestem pewien, czy w pełni rozumiem twoją sytuację, ale jednym z podejść jest zdefiniowanie klasy transferu danych i umożliwienie jej serializacji w XML. Następnie możesz deserialze XML do tablicy obiektów.

edit

nie zamierzam usunąć ten, ale myślę, że to, co napisali Andrew Hare jest bliżej do tego, co chcesz, a ja w górę głosowali go wspierające.

+0

@Steven - Przepraszam, usunąłem swój wpis, ponownie przemyślałem problem, a następnie skasowałem odpowiedź po edycji. Przepraszam za zamieszanie! –

+0

Nie ma problemu. Usuwam zduplikowany kod, aby uniknąć nieporozumień. –

3

Oto sposób zrobić to z serializacją, jeśli to twoja rzecz:

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

public static class Test 
{ 
    public static void Main(string[] args) 
    { 
     var fs = new FileStream("fruits.xml", FileMode.Open); 
     var x = new XmlSerializer(typeof(Fruits)); 
     var fruits = (Fruits) x.Deserialize(fs); 
     Console.WriteLine("{0} count: {1}", fruits.GetType().Name, fruits.fruits.Length); 
     foreach(var fruit in fruits.fruits) 
      Console.WriteLine("id: {0}, name: {1}", fruit.id, fruit.name); 
    } 
} 

[XmlRoot("fruits")] 
public class Fruits 
{ 
    [XmlElement(ElementName="fruit")] 
    public Fruit[] fruits; 
} 

public class Fruit 
{ 
    public string name; 
    public int id; 
} 
+0

Dzięki za złożenie przykładowego kodu do ciała z mojej sugestii. –

+0

Dzięki temu stało się to znacznie jaśniejsze w mojej głowie. Miałem trudności ze zrozumieniem części generycznych, ponieważ nie zrobiłem serializacji z XML-em! – harrisonmeister