XmlSerializing a Generic List<>
There's lots of good techniques out there for using the XmlSerializer to serialize a Generic List<> type. You can implement IXmlSerializable and some other trickiness.
Here's the simplest possible thing I could do to make it work while working on a hobby project over lunch today with a friend.
UPDATE: I'm a dork and didn't see the forest for the trees on this one. I don't need a parallel array at all. That's my old 1.1 brain creeping in. Thanks to folks in the comments. It works fine just like this. I'm not sure why I thought it didn't work when I tried it before. Thanks folks!
namespace Poo { public class Foo { public Foo() { FooReadings = new List(); } [XmlArray("FooReadings")] //Even this attribute isn't really needed if you accept the default.
public List<FooReading> FooReadings; } public class FooReading { public FooReading() { } public FooReading(DateTime date, decimal thing2) { this.Thing2 = thing2; this.Date = date; } public decimal Thing2; public DateTime Date; } }
The technique below is useful for other things, but not in this instance.
namespace Poo { public class Foo { public Foo() { FooReadings = new List(); } [XmlIgnore] public List<FooReading> FooReadings; [XmlArray("FooReadings")] public FooReading[] ArrayFooReadings { get { return FooReadings.ToArray(); } set { FooReadings = new List(value); } } } public class FooReading { public FooReading() { } public FooReading(DateTime date, decimal thing2) { this.Thing2 = thing2; this.Date = date; } public decimal Thing2; public DateTime Date; } }
The "Real List<>" is ignored and the "fake" one is presented as an Array in the Getters/Setter. Not pretty, to be sure.
What better ways are there that you prefer?
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
1) Leave things as is and let the Xml Serializer do things automagically for you (make sure you have getters and setters for all public properties... making your object simply a value object). Note: Only default constructors are used.
2) Implement the XmlIgnoreAttribute, XmlElementAttribute, XmlAttributeAttribute attributes and all the others in this group (as you have done here). Note (again): Only default constructors are used.
3) Explicitly implement the IXmlSerializable interface (use when you want a higher degree of control over the schema but can generally be avoided) where you implement the ReadXml and WriteXml methods (the GetSchema method can generally be left returning null).
In this case (3), you will likely want to test to ensure that your serialization and deserialization works as expected for optional elements, values, etc.
I have done this in the past like this:
Unit testing classes for serialization using the XmlSerializer: http://huntjason.spaces.live.com/blog/cns!9D2E96F2AA6AE85F!401.entry
(sorry, I am not certain how to make links in DasBlog comments).
Hope this helps,
Jason Hunt
using System;
using System.IO;
using System.Collections.Generic;
using System.Xml.Serialization;
namespace SerializeList
{
class Program
{
static void Main(string[] args)
{
Foo f = new Foo();
f.FooReadings.Add(new FooReading(DateTime.Now, 1));
f.FooReadings.Add(new FooReading(DateTime.MinValue, 2));
XmlSerializer xs = new XmlSerializer(typeof(Foo));
using (StreamWriter writer = new StreamWriter(@"c:\foo.xml"))
{
xs.Serialize(writer, f);
}
// Check your C drive for a beautious XML document
}
}
public class Foo
{
public Foo() { fooReadings = new List<FooReading>(); }
private List<FooReading> fooReadings;
public List<FooReading> FooReadings
{
get { return fooReadings; }
set { fooReadings = value; }
}
}
public class FooReading
{
public FooReading() { }
public FooReading(DateTime date, decimal thing2)
{
this.Thing2 = thing2;
this.Date = date;
}
public decimal Thing2;
public DateTime Date;
}
}
http://www.hanselman.com/blog/WhatGreatNETDevelopersOughtToKnowMoreNETInterviewQuestions.aspx
Check out the 'Senior Developers/Architects' section for serialization questions.
>;-)
So the following does not work.
public class Foo
{
public Foo() { FooReadings = new List(); }
[XmlArray("FooReadings")]
public IList<FooReading> FooReadings;//note that FooReadings is an IList not a List
}
Barry H.
>Thanks guys, you're totally right. I don't know why this "didn't work" the first time I tried it.
Comments are closed.