Deserialising derived classes using XmlAttributeOverrides
-
Hello again. I've painted myself into a corner once more - this time with a different colour of paint! I am trying to understand how to use XmlAttributeOverrides() to control the deserialisation of an XML file, but I can't seem to figure out how to tell it what I want to do. I have created a running example. Using this XML:
<?xml version="1.0" encoding="utf-8"?>
<orchestra>
<bloweythingy name="flute" reed="false"/>
<bloweythingy name="oboe" reed="true"/>
<hitythingy name="tympani" keys="false"/>
<hitythingy name="piano" keys="true"/>
</orchestra>I would like to create an
Orchestra
object that contains 2 objects of classWoodwind
(representing the contents of thebloweything
elements) and 2 of classPercussion
(representinghitythingy
content). BothWoodwind
andPercussion
are derived from classInstrument
. Additionally, I would like to do this without decorating the classes with[XmlElement]
attributes so that, later on, I will be able to programatically add newInstrument
types. To do this, I created a "registry" to which the code will be able to add an XML tag name and the class to be used to represent the data in that tag. Eventually, the registry will cache theXmlSerializer
objects to be used with each tag... but for now the serialisers are created on the fly. Here is the code to try and do this:using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;namespace Deserialising
{
class ExampleA
{
static void Main(string[] args)
{
XmlSerializer iniSerializer = new XmlSerializer(typeof(Orchestra));
TextReader iniReader = new StreamReader("C:\\Temp\\ExampleOrchestra.xml");
try
{
Orchestra DuchyOfGrandFenwickPhilharmonic = (Orchestra)iniSerializer.Deserialize(iniReader);
}
catch (Exception ex)
{
while (ex != null)
{
Console.WriteLine(ex.Message);
ex = ex.InnerException;
}
Console.ReadKey();
}
iniReader.Close();
}
}\[XmlRoot("orchestra")\] public class Orc
-
Hello again. I've painted myself into a corner once more - this time with a different colour of paint! I am trying to understand how to use XmlAttributeOverrides() to control the deserialisation of an XML file, but I can't seem to figure out how to tell it what I want to do. I have created a running example. Using this XML:
<?xml version="1.0" encoding="utf-8"?>
<orchestra>
<bloweythingy name="flute" reed="false"/>
<bloweythingy name="oboe" reed="true"/>
<hitythingy name="tympani" keys="false"/>
<hitythingy name="piano" keys="true"/>
</orchestra>I would like to create an
Orchestra
object that contains 2 objects of classWoodwind
(representing the contents of thebloweything
elements) and 2 of classPercussion
(representinghitythingy
content). BothWoodwind
andPercussion
are derived from classInstrument
. Additionally, I would like to do this without decorating the classes with[XmlElement]
attributes so that, later on, I will be able to programatically add newInstrument
types. To do this, I created a "registry" to which the code will be able to add an XML tag name and the class to be used to represent the data in that tag. Eventually, the registry will cache theXmlSerializer
objects to be used with each tag... but for now the serialisers are created on the fly. Here is the code to try and do this:using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;namespace Deserialising
{
class ExampleA
{
static void Main(string[] args)
{
XmlSerializer iniSerializer = new XmlSerializer(typeof(Orchestra));
TextReader iniReader = new StreamReader("C:\\Temp\\ExampleOrchestra.xml");
try
{
Orchestra DuchyOfGrandFenwickPhilharmonic = (Orchestra)iniSerializer.Deserialize(iniReader);
}
catch (Exception ex)
{
while (ex != null)
{
Console.WriteLine(ex.Message);
ex = ex.InnerException;
}
Console.ReadKey();
}
iniReader.Close();
}
}\[XmlRoot("orchestra")\] public class Orc
cpotting wrote:
XmlSerializer iniSerializer = new XmlSerializer(typeof(Orchestra));
It looks like you are using a wrong overload of
XmlSerializer
constructor. I can't see anywhere in your code whereXmlSerializer
is getting yourXmlAttributeOverrides
object. Try with this[^] overload instead.Navaneeth How to use google | Ask smart questions
-
Hello again. I've painted myself into a corner once more - this time with a different colour of paint! I am trying to understand how to use XmlAttributeOverrides() to control the deserialisation of an XML file, but I can't seem to figure out how to tell it what I want to do. I have created a running example. Using this XML:
<?xml version="1.0" encoding="utf-8"?>
<orchestra>
<bloweythingy name="flute" reed="false"/>
<bloweythingy name="oboe" reed="true"/>
<hitythingy name="tympani" keys="false"/>
<hitythingy name="piano" keys="true"/>
</orchestra>I would like to create an
Orchestra
object that contains 2 objects of classWoodwind
(representing the contents of thebloweything
elements) and 2 of classPercussion
(representinghitythingy
content). BothWoodwind
andPercussion
are derived from classInstrument
. Additionally, I would like to do this without decorating the classes with[XmlElement]
attributes so that, later on, I will be able to programatically add newInstrument
types. To do this, I created a "registry" to which the code will be able to add an XML tag name and the class to be used to represent the data in that tag. Eventually, the registry will cache theXmlSerializer
objects to be used with each tag... but for now the serialisers are created on the fly. Here is the code to try and do this:using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;namespace Deserialising
{
class ExampleA
{
static void Main(string[] args)
{
XmlSerializer iniSerializer = new XmlSerializer(typeof(Orchestra));
TextReader iniReader = new StreamReader("C:\\Temp\\ExampleOrchestra.xml");
try
{
Orchestra DuchyOfGrandFenwickPhilharmonic = (Orchestra)iniSerializer.Deserialize(iniReader);
}
catch (Exception ex)
{
while (ex != null)
{
Console.WriteLine(ex.Message);
ex = ex.InnerException;
}
Console.ReadKey();
}
iniReader.Close();
}
}\[XmlRoot("orchestra")\] public class Orc
Yeah, and you've misspelled
hittythingy
, as well!! :-DHenry Minute Do not read medical books! You could die of a misprint. - Mark Twain Girl: (staring) "Why do you need an icy cucumber?" “I want to report a fraud. The government is lying to us all.”
-
cpotting wrote:
XmlSerializer iniSerializer = new XmlSerializer(typeof(Orchestra));
It looks like you are using a wrong overload of
XmlSerializer
constructor. I can't see anywhere in your code whereXmlSerializer
is getting yourXmlAttributeOverrides
object. Try with this[^] overload instead.Navaneeth How to use google | Ask smart questions
Thanks Navaneeth. To answer point about where the
XmlSerializer
was getting myXmlAttributesOverrides
object: the idea was to have theOrchestra
class deserialise each<bloweythingy>
and<hittythingy>
tag as it encountered them. To do thisOrchestra
implementIXmlSerializable
and the deserialisation was done inside theReadXml()
method. So theXmlAttributeOverrides
were being assigned to theXmlSerializer ts
in theOrchestra
class, not theiniSerializer
inMain
. That was the idea. But after carefully examining the example you linked to, I now realise my mistake: I misunderstood the meaning of each parameter in theXmlAttributeOverrides.Add()
method. I had writteninstrumentXmlOverrides.Add(typeof(Instrument), kvp.Value.Name, xa);
= when told to deserialise an Instrument [parm 1], if you run across a <bloweythingy> tag [parm2] apply the rules in xa (deserialise the <bloweythingy> tags into Woodwinds) [parm 3]I thought the first 2 parms were the class being deserialised and the "alternate" tagname for that class (
Instrument
and<bloweythingy>
). In reality they are the class being deserialised and the tagname/class name of a property of that class. I should have been trying do this:instrumentXmlOverrides.Add(typeof(Orchestra), "Instrument", xa);
= when told to deserialise an Orchestra [parm 1], where you would normally expect an Instrument tag [parm2] apply the rules in xa (which should include both alternate tagnames for Instrument [bloweythingy and hittythingy] and their classes [Woodwinds and Percussion]) [parm 3]In order to do that, I had to reorganise my code so that the overrides were all constructed before ever trying to deserialise
Orchestra
. That allowed me to remove theIXmlSerializable
interface fromOrchestra
and simplify the code. Thanks again, Navaneeth. I can now move ahead with the actual application I am writing.Clive Pottinger Victoria, BC
-
Yeah, and you've misspelled
hittythingy
, as well!! :-DHenry Minute Do not read medical books! You could die of a misprint. - Mark Twain Girl: (staring) "Why do you need an icy cucumber?" “I want to report a fraud. The government is lying to us all.”
Henry Minute wrote:
Yeah, and you've misspelled hittythingy, as well!! Big Grin
I checked AskOford.com first - but appearently, it is not a term in common usage in England. So I was left to guess. :-O I have corrected my code ;)
Clive Pottinger Victoria, BC
-
Thanks Navaneeth. To answer point about where the
XmlSerializer
was getting myXmlAttributesOverrides
object: the idea was to have theOrchestra
class deserialise each<bloweythingy>
and<hittythingy>
tag as it encountered them. To do thisOrchestra
implementIXmlSerializable
and the deserialisation was done inside theReadXml()
method. So theXmlAttributeOverrides
were being assigned to theXmlSerializer ts
in theOrchestra
class, not theiniSerializer
inMain
. That was the idea. But after carefully examining the example you linked to, I now realise my mistake: I misunderstood the meaning of each parameter in theXmlAttributeOverrides.Add()
method. I had writteninstrumentXmlOverrides.Add(typeof(Instrument), kvp.Value.Name, xa);
= when told to deserialise an Instrument [parm 1], if you run across a <bloweythingy> tag [parm2] apply the rules in xa (deserialise the <bloweythingy> tags into Woodwinds) [parm 3]I thought the first 2 parms were the class being deserialised and the "alternate" tagname for that class (
Instrument
and<bloweythingy>
). In reality they are the class being deserialised and the tagname/class name of a property of that class. I should have been trying do this:instrumentXmlOverrides.Add(typeof(Orchestra), "Instrument", xa);
= when told to deserialise an Orchestra [parm 1], where you would normally expect an Instrument tag [parm2] apply the rules in xa (which should include both alternate tagnames for Instrument [bloweythingy and hittythingy] and their classes [Woodwinds and Percussion]) [parm 3]In order to do that, I had to reorganise my code so that the overrides were all constructed before ever trying to deserialise
Orchestra
. That allowed me to remove theIXmlSerializable
interface fromOrchestra
and simplify the code. Thanks again, Navaneeth. I can now move ahead with the actual application I am writing.Clive Pottinger Victoria, BC
Great. Happy to help :thumbsup:
Navaneeth How to use google | Ask smart questions