I wonder if it's possible to define the element names when serializing my custom collection of a certain base type. Consider the following example (I'm using the fruit example here :)):
[DataContract(Name = "Bowl")]
public class Bowl
{
[DataMember]
public List<Fruit> Fruits { get; set; }
}
[DataContract(Name = "Fruit")]
public abstract class Fruit
{
}
[DataContract(Name = "Apple", Namespace = "")]
public class Apple : Fruit
{
}
[DataContract(Name = "Banana", Namespace = "")]
public class Banana : Fruit
{
}
When serializing:
var bowl = new Bowl() { Fruits = new List<Fruit> { new Apple(), new Banana() } };
var serializer = new DataContractSerializer(typeof(Bowl), new[] { typeof(Apple), typeof(Banana) });
using (var ms = new MemoryStream())
{
serializer.WriteObject(ms, bowl);
ms.Position = 0;
Console.WriteLine(System.Text.Encoding.UTF8.GetString(ms.ToArray()));
}
Would give me an output of:
<Bowl xmlns="http://schemas.datacontract.org/2004/07/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Fruits>
<Fruit i:type="Apple" xmlns="" />
<Fruit i:type="Banana" xmlns="" />
</Fruits>
</Bowl>
What I really would like is an output where the Fruit elements is replaces with their proper class names. I.e.:
<Bowl xmlns="http://schemas.datacontract.org/2004/07/">
<Fruits>
<Apple />
<Banana />
</Fruits>
</Bowl>
Is it possible to do with DataContractSerializer
or do I have to write my own logic for it with XmlWriter?
If you want lots of control over the xml output, you should be annotating it for XmlSerializer
, not DataContractSerializer
. For example:
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
public class Bowl {
[XmlArray("Fruits")]
[XmlArrayItem("Apple", typeof(Apple))]
[XmlArrayItem("Banana", typeof(Banana))]
public List<Fruit> Fruits { get; set; }
}
public abstract class Fruit { }
public class Apple : Fruit { }
public class Banana : Fruit { }
static class Program {
static void Main() {
var ser = new XmlSerializer(typeof(Bowl));
var obj = new Bowl {
Fruits = new List<Fruit> {
new Apple(), new Banana()
}
};
ser.Serialize(Console.Out, obj);
}
}