views:

59

answers:

1

Trying to "thaw" serialized objects that have been stored in an XML file:

In LinqToSQL, I can (with a suitably decorated class) do this type of thing:

   [Table(Name="Plants")]
   public class Plant
   {
      [Column(Name = "Id", IsPrimaryKey = true)]
      public int Id { get; set; }
      [Column(Name = "Genus")]
      public string Genus { get; set; }
      [Column(Name = "Species")]
      public string Species { get; set; }
      [Column(Name = "CommonName")]
      public string CommonName { get; set; }
      ...
    }

then later do this:

 using (DataContext db = new DataContext(ConnectString))
 {
    plants = (
       from d in db.GetTable<Plant>()
       select d).ToList();
 }

and the data from the SQL table are used to populate a List<> of Plant objects.

But with LinqToXML I can't seem to do that trick, instead I have to do something like this:

<!-- XML File -->
<Plants>
   <Plant>
      <Genus>Quercus</Genus>
      <Species>alba</Species>
      <CommonName>White Oak</CommonName>
   </Plant>
   ...
</Plants>

   // Class
   [DataContract]
   [XmlRoot("Plants")]
   public class Plant
   {
      [DataMember]
      public string Genus { get; set; }
      [DataMember]
      public string Species { get; set; }
      [DataMember]
      public string CommonName { get; set; }
      ...
    }

 // Code -- note: I already have the XML file in an XDocument called "doc"
 IEnumerable<XElement> items = (from item in doc.Descendants("Plant")
   where item.Element("Genus").Value.Equals("Quercus")
   select item);

 List<Plant> plants = new List<Plant>();
 foreach (XElement item in items)
 {
    Plant a = new Plant();
    a.Genus = item.Element("Genus").Value;
    a.Species = item.Element("Species").Value;
    XElement ex = item.Element("CommonName");
    if ((null == ex) || ex.IsEmpty) { } else { a.Example = ex.Value; }
    plants.Add(a);
 }

Given that I would like to make this serialization / deserialization general purpose, is there a way to do this without resorting to reflection? I can use the the XmlSerializer, but that, too, involves a lot of messing around with MemoryStreams and using them as either XmlWriter or XmlReaders when all I want is to make my class automagically go to/from an XML file. Just wondering if I'm failing to connect the dots here...

+1  A: 

I fear you are mixing up DataContracts and LinqToXML.

You can use DataContracts to deserialize an Xml document to an object.

After deserializing you should be able to use LinqToObjects to query the dataset.

Give this a try:

[CollectionDataContract(Name = "Plants", ItemName = "Plant", Namespace = "")]
class Plants: List<Plant> { }

[DataContract(Name = "Plant", Namespace = "")]
class Plant
{
    [DataMember()]
    public string Genus { get; set; }

    [DataMember()]
    public string Species { get; set; }

    [DataMember()]
    public string CommonName { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        using (var fs = new FileStream("Plants.xml", FileMode.Open))
        using (var reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()))
        {
            var ser = new DataContractSerializer(typeof(Plants));

            var plants = ser.ReadObject(reader) as Plants;

            foreach (var plant in plants)
                Console.WriteLine("{0}, {1}, {2}", plant.Genus, plant.Species, plant.CommonName);
        }

        Console.ReadKey();
    }
}
Yannick M.