Click here to Skip to main content
15,890,186 members
Home / Discussions / C#
   

C#

 
GeneralRe: What is an instance variable and how do you declare one? Pin
Christian Graus2-Aug-09 13:54
protectorChristian Graus2-Aug-09 13:54 
AnswerRe: What is an instance variable and how do you declare one? Pin
Christian Graus2-Aug-09 13:52
protectorChristian Graus2-Aug-09 13:52 
QuestionWhat the heck does this mean? [modified] Pin
Nathan Revka2-Aug-09 10:56
Nathan Revka2-Aug-09 10:56 
AnswerRe: What the heck does this mean? Pin
Richard Andrew x642-Aug-09 11:07
professionalRichard Andrew x642-Aug-09 11:07 
AnswerRe: What the heck does this mean? Pin
Christian Graus2-Aug-09 11:38
protectorChristian Graus2-Aug-09 11:38 
QuestionAdvice Pin
michael_jhons2-Aug-09 8:16
michael_jhons2-Aug-09 8:16 
AnswerRe: Advice Pin
Manas Bhardwaj2-Aug-09 9:04
professionalManas Bhardwaj2-Aug-09 9:04 
QuestionDeserialising derived classes using XmlAttributeOverrides Pin
Clive D. Pottinger2-Aug-09 6:39
Clive D. Pottinger2-Aug-09 6:39 
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 class Woodwind (representing the contents of the bloweything elements) and 2 of class Percussion (representing hitythingy content). Both Woodwind and Percussion are derived from class Instrument.

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 new Instrument 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 the XmlSerializer 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 Orchestra : IXmlSerializable
    {
        /// <summary>
        /// Records the xml element tags used to create each of instrument types.
        /// This is done to avoid having to decorate each class with an XmlElement
        /// tag (a requirement of the real application - any decoration seen in this
        /// example is only there to simplify the example).
        /// </summary>
        private Dictionary<string, Type> RegisteredElements;

        private XmlAttributeOverrides instrumentXmlOverrides;

        public Orchestra()
        {
            this.RegisteredElements = new Dictionary<string, Type>();
            this.Compliment = new List<Instrument>();

            // Create a registry of xml tags and which classes to use to deserialise them.
            // In the real application, the registry is populated by other methods in other 
            // classes.
            RegisteredElements.Add("bloweythingy", typeof(Woodwind));
            RegisteredElements.Add("hitythingy", typeof(Percussion));

            // Use the registry to create the rules describing how to deserialise the 
            // various silly tag names found in the XML into classes with sensible names.
            instrumentXmlOverrides = new XmlAttributeOverrides();
            foreach (KeyValuePair<string, Type> kvp in RegisteredElements)
            {
                // create the deserialisation override for this 
                XmlElementAttribute xea = new XmlElementAttribute(kvp.Key, kvp.Value);
                XmlAttributes xa = new XmlAttributes();
                xa.XmlElements.Add(xea);

                // variation A:
                instrumentXmlOverrides.Add(typeof(Instrument), kvp.Value.Name, xa);
                // variation B:
                //instrumentXmlOverrides.Add(typeof(Instrument), kvp.Key, xa);
                // variation C:
                //instrumentXmlOverrides.Add(kvp.Value, kvp.Value.Name, xa);
            }
        }

        /// <summary>Holds all the instruments in this Orchestra</summary>
        public List<Instrument> Compliment { get; set; }

        #region IXmlSerializable methods
        public XmlSchema GetSchema() { return null; }  // not interested in schemas

        public void ReadXml(XmlReader reader)
        {

            reader.ReadStartElement();
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                // subvariation: 1
                XmlSerializer ts = new XmlSerializer(typeof(Instrument), instrumentXmlOverrides);

                // subvariation: 2
                //Type elemType = RegisteredElements[reader.Name];
                //XmlSerializer ts = new XmlSerializer(elemType, instrumentXmlOverrides);

                this.Compliment.Add((Instrument)(ts.Deserialize(reader)));
            }
            reader.ReadEndElement();
        }

        public void WriteXml(XmlWriter writer) { }  // not interested in serialising
        #endregion
    }

    public class Instrument
    {
        [XmlAttribute("name")]
        public string Name { get; set; }
    }

    public class Woodwind : Instrument
    {
        [XmlAttribute("reed")]
        public bool hasReed { get; set; }
    }

    public class Percussion : Instrument
    {
        [XmlAttribute("keys")]
        public bool hasKeys { get; set; }
    }
}

I have tried all combinations of variations A, B and C with subvariations 1 and 2... but to no avail. I keep being told that bloweything is not expected or that the root element is missing. The combination that is uncommented above (A and 1) is the one that I (IMHO) think should work. The following annotations are intended to show what I thought the code would do:
<small>when kvp = {"bloweything", typeof(Woodwind)}:</small>
  XmlElementAttribute xea = new XmlElementAttribute(kvp.Key, kvp.Value); 
    <small>= associate <bloweything> tags with Woodwind classes</small>
  XmlAttributes xa = new XmlAttributes(); 
  xa.XmlElements.Add(xea);  
    <small>= we now have a new rule: <bloweythingy> becomes Woodwind (deserialising) and Woodwinds are written as <bloweythingy> (serialising)</small>

  instrumentXmlOverrides.Add(typeof(Instrument), kvp.Value.Name, xa); 
    <small>= 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]</small>
  
  ...

<small>when reader.Name = "bloweythingy":</small>
  XmlSerializer ts = new XmlSerializer(typeof(Instrument), instrumentXmlOverrides);
    <small>= I'm telling you to deserialise an Instrument using the above stated rules, so you should turn the <bloweythingy> into a Woodwind</small>

  this.Compliment.Add((Instrument)(ts.Deserialize(reader)));
    <small>= @#$%# - WHY WON'T .NET LISTEN TO ME?!?!?  I HATE COMPUTERS</small>


Any help would be appreciated. Thanks.

Clive Pottinger
Victoria, BC

AnswerRe: Deserialising derived classes using XmlAttributeOverrides Pin
N a v a n e e t h2-Aug-09 7:55
N a v a n e e t h2-Aug-09 7:55 
GeneralRe: Deserialising derived classes using XmlAttributeOverrides Pin
Clive D. Pottinger3-Aug-09 6:08
Clive D. Pottinger3-Aug-09 6:08 
GeneralRe: Deserialising derived classes using XmlAttributeOverrides Pin
N a v a n e e t h3-Aug-09 16:27
N a v a n e e t h3-Aug-09 16:27 
AnswerRe: Deserialising derived classes using XmlAttributeOverrides Pin
Henry Minute2-Aug-09 9:09
Henry Minute2-Aug-09 9:09 
GeneralRe: Deserialising derived classes using XmlAttributeOverrides Pin
Clive D. Pottinger3-Aug-09 6:13
Clive D. Pottinger3-Aug-09 6:13 
QuestionAccessing the file of a T-SQL BACKUP call Pin
Uwe Keim2-Aug-09 6:00
sitebuilderUwe Keim2-Aug-09 6:00 
AnswerRe: Accessing the file of a T-SQL BACKUP call Pin
N a v a n e e t h2-Aug-09 7:40
N a v a n e e t h2-Aug-09 7:40 
GeneralRe: Accessing the file of a T-SQL BACKUP call Pin
Uwe Keim2-Aug-09 19:15
sitebuilderUwe Keim2-Aug-09 19:15 
AnswerRe: Accessing the file of a T-SQL BACKUP call Pin
Mycroft Holmes2-Aug-09 12:21
professionalMycroft Holmes2-Aug-09 12:21 
GeneralRe: Accessing the file of a T-SQL BACKUP call Pin
Uwe Keim2-Aug-09 19:15
sitebuilderUwe Keim2-Aug-09 19:15 
Questionnotify icon Pin
Vivek Vijayan2-Aug-09 2:18
Vivek Vijayan2-Aug-09 2:18 
AnswerRe: notify icon Pin
Manas Bhardwaj2-Aug-09 2:27
professionalManas Bhardwaj2-Aug-09 2:27 
GeneralRe: notify icon Pin
Abhijit Jana2-Aug-09 2:38
professionalAbhijit Jana2-Aug-09 2:38 
GeneralRe: notify icon Pin
Manas Bhardwaj2-Aug-09 2:39
professionalManas Bhardwaj2-Aug-09 2:39 
AnswerRe: notify icon Pin
CoderForEver2-Aug-09 8:06
CoderForEver2-Aug-09 8:06 
QuestionCustom user control Pin
Jon Henry2-Aug-09 1:45
Jon Henry2-Aug-09 1:45 
AnswerRe: Custom user control Pin
Super Lloyd2-Aug-09 2:38
Super Lloyd2-Aug-09 2:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.