Serializing and deserializing multiple generic collections using DataContractSerializer
The DataContractSerializer class is the successor of the XmlSerializer class. Introduced together with WCF. This one is also being used by WCF for serialization by default. You can of course always switch back to the good old XmlSerializer if you want to.
Anyway, if you wanted to serialize a collection with the XmlSerializer you had to use the XmlArrayAttribute.
With the DataContractSerializer you get the CollectionDataContractAttribute class. Personally, I think that serializing a generic list via the DataContractSerializer is easier then with the XmlSerializer. Even with the DataContractSerializer I think they could have done it easier. You’ll see what I mean in a minute.
Let’s look at some code.
The example
The example will be a simple to-do list. You can specify a name, a due data and multiple tags.
Creating the necessary classes
1: [DataContract(Name = "TodoList", Namespace = "http://www.mshelp.be")]
2: public class TodoList
3: {
4: [DataMember(Name = "Todos")]
5: public InternalTodoList Todo { get; set; }
6: public TodoList()
7: {
8: Todo = new InternalTodoList();
9: }
10: }
11: [DataContract(Name = "Todo")]
12: public class Todo
13: {
14: public Todo()
15: {
16: Name = String.Empty;
17: DueDate = DateTime.Now;
18: Tags = new TagList();
19: }
20: [DataMember(Name = "Name")]
21: public string Name { get; set; }
22: [DataMember(Name = "DueDate")]
23: public DateTime DueDate { get; set; }
24: [DataMember(Name = "Tags")]
25: public TagList Tags { get; set; }
26: }
27: [CollectionDataContract(ItemName = "Tag")]
28: public class TagList : List<string> { }
29:
30: [CollectionDataContract(ItemName = "Todo")]
31: public class InternalTodoList : List<Todo> { }
The class TodoList will contain all the different todo’s and the Todo class contains the properties we already discussed. As you can see I also have two other classes. The TagList and the InternalTodoList, both marked with the CollectionDataContract attribute. You also see that these classes contain the generic lists. I did this because you can only add the CollectionDataContract attribute to a class or struct.
How to Serialize
As you can see I use the XmlDictionaryWriter class, which was also introduced with .NET 3.0.
1: static void SerializeTodoList()
2: {
3: var dcs = new DataContractSerializer(typeof(TodoList));
4: var ds = new FileStream(@"c:\MyTodoList.xml",FileMode.Create);
5: var xdw = XmlDictionaryWriter.CreateTextWriter(ds, Encoding.UTF8);
6: dcs.WriteObject(xdw, _myTodoList);
7: xdw.Flush();
8: someStream.Flush();
9: }
How to Deserialize
For the desrialization we’ll use the XmlDictionaryReader class together with the DataContractSerializer.
1: static void DeserializeTodoList()
2: {
3: var dcs = new DataContractSerializer(typeof(TodoList));
4: var ds = new FileStream(@"c:\MyTodoList.xml", FileMode.Open);
5: var xdr = XmlDictionaryReader.CreateTextReader(ds, new XmlDictionaryReaderQuotas());
6: _myTodoList = (TodoList)dcs.ReadObject(xdr);
7: }
Testing the code
Now for a simple test, let’s add some to-do’s. Don’t forget to define the _myTodoList, which is of course an instance of the TodoList class.
1: static void InitTodoList()
2: {
3: _myTodoList = new TodoList();
4: var todo1 = new Todo {Name = "Fix some issues"};
5: var tlist1 = new TagList {"fix", "issues"};
6: todo1.Tags = tlist1;
7: _myTodoList.Todo.Add(todo1);
8:
9: var todo2 = new Todo {Name = "Fix stuff"};
10: var tlist2 = new TagList {"fix", "stuff"};
11: todo2.Tags = tlist2;
12: _myTodoList.Todo.Add(todo2);
13: }
The aforementioned code will generate the following XML.
1: <TodoList xmlns="http://www.mshelp.be" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
2: <Todos xmlns:a="http://schemas.datacontract.org/2004/07/CollectionDataContractAtt">
3: <a:Todo>
4: <a:DueDate>2009-06-20T15:19:57.196+02:00</a:DueDate>
5: <a:Name>Fix some issues</a:Name>
6: <a:Tags>
7: <a:Tag>fix</a:Tag>
8: <a:Tag>issues</a:Tag>
9: </a:Tags>
10: </a:Todo>
11: <a:Todo>
12: <a:DueDate>2009-06-20T15:19:57.201+02:00</a:DueDate>
13: <a:Name>Fix stuff</a:Name>
14: <a:Tags>
15: <a:Tag>fix</a:Tag>
16: <a:Tag>stuff</a:Tag>
17: </a:Tags>
18: </a:Todo>
19: </Todos>
20: </TodoList>
Hope this post was informative and if you have comments, remarks. Please let me know, any constructive feedback is welcome.