0

I tried following the Microsoft website documentation for addressing the above question. However, I'm not able to find the answer. So I tried writing the code, but my object is not getting serialized when I added more derived classes.

Here goes the code:

using System;
using System.IO;
using System.Xml.Serialization;
using System.Collections.Generic;
public class Orchestra
{
    // public Instrument[] Instruments;
    public List<Instrument> Instruments;
    public int i;
    public float f;
    public string s1;
    public string s2;
    public B bc;
}
public class B
{
    public double dd;
}
public class Instrument
{
    public string Name;
}

public class Brass : Instrument
{
    public bool IsValved;
}
public class Percussion : Instrument
{
    public string name;
}
public class Run
{
    public static void Main()
    {
        Run test = new Run();
        test.SerializeObject("Override.xml");
        test.DeserializeObject("Override.xml");
    }

    public void SerializeObject(string filename)
    {
        /* Each overridden field, property, or type requires 
        an XmlAttributes object. */
        XmlAttributes attrs = new XmlAttributes();

        /* Create an XmlElementAttribute to override the 
        field that returns Instrument objects. The overridden field
        returns Brass objects instead. */
        XmlElementAttribute attr = new XmlElementAttribute();
        attr.ElementName = "Brass";
        attr.Type = typeof(Brass);

        attrs.XmlElements.Add(attr);
      //  attrs.XmlArrayItems.Add(attr);

       attr.ElementName = "Percussion";
        attr.Type = typeof(Percussion);
        // Add the element to the collection of elements.
        attrs.XmlElements.Add(attr);

        // Create the XmlAttributeOverrides object.
        XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();

        /* Add the type of the class that contains the overridden 
        member and the XmlAttributes to override it with to the 
        XmlAttributeOverrides object. */
        attrOverrides.Add(typeof(Orchestra), "Instruments", attrs);

        // Create the XmlSerializer using the XmlAttributeOverrides.
        XmlSerializer s =
        new XmlSerializer(typeof(Orchestra), attrOverrides);

        // Writing the file requires a TextWriter.
        TextWriter writer = new StreamWriter(filename);

        // Create the object that will be serialized.
        Orchestra band = new Orchestra();

        // Create an object of the derived type.
        //Brass i = new Brass();
        //i.Name = "Trumpet";
        //i.IsValved = true;
        //Instrument[] myInstruments = { i };
        //band.Instruments = myInstruments;
        List<Instrument> myInstruments = new List<Instrument>();
        myInstruments.Add(new Brass() { Name = "Trumpet", IsValved = true });
        myInstruments.Add(new Percussion() { Name = "Percussion", name = "Mridangam" });
        band.Instruments = myInstruments;
        band.i = 128;
        band.f = 5.678f;
        band.s1 = "Hi!";
        band.s2 = "GOOD!!!";
        B b = new B();
        b.dd = 2.35674848;
        band.bc = b;
        // Serialize the object.
        s.Serialize(writer, band);
        writer.Close();
    }

    public void DeserializeObject(string filename)
    {
        XmlAttributeOverrides attrOverrides =
           new XmlAttributeOverrides();
        XmlAttributes attrs = new XmlAttributes();

        // Create an XmlElementAttribute to override the Instrument.
        XmlElementAttribute attr = new XmlElementAttribute();
        attr.ElementName = "Brass";
        attr.Type = typeof(Brass);

        // Add the element to the collection of elements.
        attrs.XmlElements.Add(attr);

        attrOverrides.Add(typeof(Orchestra), "Instruments", attrs);

        // Create the XmlSerializer using the XmlAttributeOverrides.
        XmlSerializer s =
        new XmlSerializer(typeof(Orchestra), attrOverrides);

        FileStream fs = new FileStream(filename, FileMode.Open);
        Orchestra band = (Orchestra)s.Deserialize(fs);
        Console.WriteLine(band.i);
        Console.WriteLine(band.f);
        Console.WriteLine(band.s1);
        Console.WriteLine(band.s2);
        Console.WriteLine(band.bc.dd);
        Console.WriteLine("Brass:");

        /* The difference between deserializing the overridden 
        XML document and serializing it is this: To read the derived 
        object values, you must declare an object of the derived type 
        (Brass), and cast the Instrument instance to it. */
        //Brass b;
        //Percussion p;
        Brass b;
       // Percussion p;
        //b = (Brass)i;
       // int ii = 0;
        foreach (Instrument i in band.Instruments)
        //foreach(Instrument i in band.List<Instrument>)
        {
            //        int i = 0;
         //   ii++;
          //  if (ii == 1)
         //   {
                b = (Brass)i;
                Console.WriteLine(
                    b.Name + "\n" +
                    b.IsValved);
           // }
            /*if (ii == 2)
            {
                p = (Percussion)i;
                Console.WriteLine(
                    p.Name + "\n" +
                    p.name);

            }*/
        }
    }
}

I even tried using XmlArrayItem. Could anyone guide how to go about this?

Ondrej Tucny
  • 27,626
  • 6
  • 70
  • 90
R.Anush
  • 37
  • 9
  • Have you tried "[Serializable]" before the class Declare? – Vinh Can Code Jul 28 '18 at 11:54
  • 1
    @VinhCC The `[Serializable]` attribute is **not** related to XML serialization. – Ondrej Tucny Jul 28 '18 at 13:37
  • *"is not getting serialized* — so what error message are you getting? What does the serialized XML look like? Please provide a minimal, complete and verifiable example: https://stackoverflow.com/help/mcve – Ondrej Tucny Jul 28 '18 at 13:39
  • Specify the exact problem! Your code doesn't compile? Compiles but does not start? Starts but crashes with an exception? It works out to the end, but gives the wrong result? – Alexander Petrov Jul 28 '18 at 13:42

1 Answers1

0

You have to add a new class Instruments to your code. See code below :

using System;
using System.IO;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Xml;

public class Orchestras
{
    public List<Orchestra> orchestras = new List<Orchestra>();
}
public class Orchestra
{
    [XmlElement]
    public List<Instrument> Instruments { get; set; }
    public int i;
    public float f;
    public string s1;
    public string s2;
    public B bc;
}
public class B
{
    public double dd;
}
[XmlInclude(typeof(Brass))]
[XmlInclude(typeof(Percussion))]
public class Instrument
{
    public string Name;
}

public class Brass : Instrument
{
    public bool IsValved;
}
public class Percussion : Instrument
{
    public string name;
}
public class Run
{
    const string FILENAME = @"c:\temp\test.xml";
    public static void Main()
    {
        Run test = new Run();
        test.SerializeObject(FILENAME);
        test.DeserializeObject(FILENAME);
    }

    public void SerializeObject(string filename)
    {
        Orchestras orchastras = new Orchestras();
        Orchestra orchestra1 = new Orchestra();
        orchastras.orchestras.Add(orchestra1);
        List<Instrument> instruments = new List<Instrument>() { 
            new Instrument() { Name = "Brass"},
            new Instrument() { Name = "Percussion"}
        };

        orchestra1.Instruments = instruments;


        // Create the XmlSerializer using the XmlAttributeOverrides.
        XmlSerializer s = new XmlSerializer(typeof(Orchestras));


        // Writing the file requires a TextWriter.
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        XmlWriter writer = XmlWriter.Create(filename,settings);

        // Create the object that will be serialized.
        Orchestra band = new Orchestra();
        orchastras.orchestras.Add(band);
        // Create an object of the derived type.
        //Brass i = new Brass();
        //i.Name = "Trumpet";
        //i.IsValved = true;
        //Instrument[] myInstruments = { i };
        //band.Instruments = myInstruments;
        List<Instrument> myInstruments = new List<Instrument>();
        myInstruments.Add(new Brass() { Name = "Trumpet", IsValved = true });
        myInstruments.Add(new Percussion() { Name = "Percussion", name = "Mridangam" });
        band.Instruments = myInstruments;
        band.i = 128;
        band.f = 5.678f;
        band.s1 = "Hi!";
        band.s2 = "GOOD!!!";
        B b = new B();
        b.dd = 2.35674848;
        band.bc = b;
        // Serialize the object.
        s.Serialize(writer, orchastras);
        writer.Close();
    }

    public void DeserializeObject(string filename)
    {

        // Create the XmlSerializer using the XmlAttributeOverrides.
        XmlSerializer s =
           new XmlSerializer(typeof(Orchestras));

        FileStream fs = new FileStream(filename, FileMode.Open);
        Orchestras band = (Orchestras)s.Deserialize(fs);
        Console.WriteLine(band.orchestras[1].i);
        Console.WriteLine(band.orchestras[1].f);
        Console.WriteLine(band.orchestras[1].s1);
        Console.WriteLine(band.orchestras[1].s2);
        Console.WriteLine(band.orchestras[1].bc.dd);
        Console.WriteLine("Brass:");

        /* The difference between deserializing the overridden 
        XML document and serializing it is this: To read the derived 
        object values, you must declare an object of the derived type 
        (Brass), and cast the Instrument instance to it. */
        //Brass b;
        //Percussion p;
        Instrument b;
        // Percussion p;
        //b = (Brass)i;
        // int ii = 0;
        foreach (Instrument i in band.orchestras[1].Instruments)
        //foreach(Instrument i in band.List<Instrument>)
        {
            //        int i = 0;
            //   ii++;
            //  if (ii == 1)
            //   {
            b = i;
            Console.WriteLine(
                b.Name + "\n");

            // }
            /*if (ii == 2)
            {
                p = (Percussion)i;
                Console.WriteLine(
                    p.Name + "\n" +
                    p.name);

            }*/
        }
    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • Could You please explain me the code that you have written, I am unable to understand the code you have written – R.Anush Jul 29 '18 at 04:37
  • The code is the same as you posted except I added a new class Orchestras and put two orchestras into the class. I also used a XmlWriter instead of your StreamWriter. I also had to add XmlInclude because you have two classes that inherit the same base class. – jdweng Jul 29 '18 at 08:26
  • How to serialize the same code if all the member variables are private? Can i still use XmIInclude,Typeof, XmlElement, and instantiate an object of DataContract Serializer() instead of XMlSerializer? – R.Anush Aug 03 '18 at 09:48
  • I've never tried it. I think it should work , but you should try it yourself. – jdweng Aug 03 '18 at 10:31
  • ok thanks jdweng. i will try it and come back – R.Anush Aug 22 '18 at 06:53