2009-09-22 19 views
6

¿Hay una manera de tomar un archivo XML en cuestión y convertir (preferiblemente usando C# genéricos) en una lista IEnumerable hormigón de T, donde T es mi clase concretaXML para IEnumerable <T>

Así, por ejemplo, que puede tener una archivo XML como

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

y me gustaría ver una lista de una fruta se opone

donde tiene propiedades como

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

Asumo que iba a necesitar algún tipo de mapeo si iba a utilizar los genéricos, como me gustaría que esto funcione para idealmente la interfaz IFruit (no estoy seguro si eso es posible)

Gracias de antemano

Respuesta

9

Teniendo en cuenta los siguientes tipos:

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; } 
} 

creo que se podría hacer algo como esto:

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) 
      }); 
    } 

¿Qué usted llamaría así:

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

Me gusta esta solución, y en realidad es compatible con la serialización de XML. El único comentario que haré es que las convenciones de .NET generalmente requieren que los campos públicos (o, más realistamente, las propiedades públicas) comiencen con una letra mayúscula, pero esa fue la decisión de Harrison, no la tuya. –

+0

Bueno. Para llevar esto un paso más allá, me imagino que habría subclases para cada tipo de fruta para un método genérico como este para devolver nodos de fruta de un tipo coincidente, es decir, si T = Naranja solo devuelve aquellos frutos cuyo nombre es Naranja . El método podría comparar el tipo de (T) .Nombre con el nombre de la fruta del xml y excluir otros ... solo mis 2 centavos –

+0

Eres un genio, salvaste mi montón de trabajo – Moons

0

No estoy seguro de entender completamente sus circunstancias, pero un enfoque es definir una clase de transferencia de datos y hacerla serializable en XML. Luego puede deserializar el XML en una matriz de objetos.

edición

no voy a borrar esto, pero creo que lo que Andrew Hare publicada está más cerca de lo que quiere, y lo que he votado en up-apoyo.

+0

@Steven - Lo siento, eliminé mi publicación, volví a plantearme el problema y luego eliminé mi respuesta después de una edición. ¡Perdón por la confusion! –

+0

No hay problema. Eliminaré el código duplicado para evitar confusiones. –

3

Aquí está una manera para hacerlo con serialización, si eso es lo suyo:

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

Gracias por juntar código de muestra para la carne mi sugerencia fuera del manguito. –

+0

Gracias esto lo ha aclarado mucho en mi cabeza. Tuve dificultades para descifrar los genéricos, ya que no hice mucha serialización con XML, ¡perfecto! – harrisonmeister

Cuestiones relacionadas