I'm serializing my DTO to XML messages using DataContractSerializer, however I need to support 2 XML formats, they are identical in structure but differ in element naming, so I need to support an alternative set of DataMemeber[Name=""] attributes on my DTO's. How to solve this without cloning my DTO classes? I need to support both formats at runtime, so preproccessor derectives will not suffice.
Firstly, for fine-grained xml serialization, XmlSerializer
is preferable to DataContractSerializer
(which is fine as a general purpose serializer, but is hard to take seriously as an xml serializer when it can't even handle attributes).
Secondly, XmlSerializer
has options for this - in particalar, XmlAttributeOverrides
. With an XmlAttributeOverrides
you can configure the entire setup for your type at runtime, then just pass it in to the XmlSerializer
constructor. Important warning: do this once and store the serializer instance, otherwise you will haemorrhage dynamic assemblies.
[XmlRoot("foo")]
public class Foo
{
[XmlElement("bar")]
public string Bar { get; set; }
}
class Program
{
static void Main()
{
XmlAttributeOverrides xao = new XmlAttributeOverrides();
xao.Add(typeof(Foo), new XmlAttributes { XmlRoot =
new XmlRootAttribute("alpha")});
xao.Add(typeof(Foo), "Bar", new XmlAttributes { XmlElements = {
new XmlElementAttribute("beta") } });
var ser = new XmlSerializer(typeof (Foo), xao);
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("","");
ser.Serialize(Console.Out, new Foo { Bar = "abc"}, ns);
}
}
with output:
<alpha>
<beta>abc</beta>
</alpha>