2

I'll try to make my problem as simple, as possible. Below are 2 sample programs to demonstrate it. U can just copy&paste it into Visual Studio, if U need to analyze it.

Feel free to comment and correct my English. Hope you can understand me.

My target is: We have 2 classes - BaseClass and DerivedClass.

We need to:

  1. Create an instance of DerivedClass
  2. Assign it into a variable of type BaseClass
  3. Serialize that variable into a XML file
  4. Deserialize that file into a variable of type BaseClass
  5. That variable should contain an object of type DerivedClass

The first example program is using "built-in" serialization - and works just fine.

BUT i want to have more control over serialization process (using IXmlSerializable interface) AND achieve the same effect.

First example:

[Serializable]
public class BaseClass
{
    public string property1;
    public string property2;

    public BaseClass()
    {
    }
}

[Serializable]
public class DerivedClass : BaseClass
{
    public string property3;

    public DerivedClass()
    {
    }
}

class Program
{
    static void Main(string[] args)
    {
        XmlSerializer mySer = new XmlSerializer(typeof(BaseClass), new Type [] {typeof(DerivedClass)});

        BaseClass exampleBaseClass;
        DerivedClass exampleDerivedClass = new DerivedClass();
        exampleDerivedClass.property1 = "Foo";
        exampleDerivedClass.property2 = "Bar";
        exampleDerivedClass.property3 = "Sth";

        exampleBaseClass = exampleDerivedClass;

        Console.WriteLine(exampleBaseClass.GetType());   // <----- 1
        StreamWriter sw = new StreamWriter("test.xml");
        mySer.Serialize(sw, exampleBaseClass);           // <----- 2
        sw.Close();
        StreamReader sr = new StreamReader("test.xml");
        exampleBaseClass = (BaseClass)mySer.Deserialize(sr);
        Console.WriteLine(exampleBaseClass.GetType());   // <----- 3
        Console.ReadKey();
    }
}
  1. This prints "ConsoleApplication1.DerivedClass - and it's OK.
  2. This creates file, that contains all 3 properties - and it's OK.
  3. This prints "ConsoleApplication1.DerivedClass - and it's OK.

Second example:

[Serializable]
public class BaseClass : IXmlSerializable
{
    public string property1;
    public string property2;

    public BaseClass()
    {
    }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }
    public virtual void WriteXml(XmlWriter writer)
    {
        writer.WriteElementString("property1", property1);
        writer.WriteElementString("property2", property2);
    }
    public virtual void ReadXml(XmlReader reader)
    {
        while (reader.Read())
            switch (reader.Name)
            {
                case "property1":
                    property1 = reader.Value;
                    break;
                case "property2":
                    property2 = reader.Value;
                    break;
            }
    }        
}

[Serializable]
public class DerivedClass : BaseClass, IXmlSerializable
{
    public string property3;

    public DerivedClass()
    {
    }


    public override void WriteXml(XmlWriter writer)
    {
        writer.WriteElementString("property1", property1);
        writer.WriteElementString("property2", property2);
        writer.WriteElementString("property3", property3);
    }

    public override void ReadXml(XmlReader reader)
    {
        while (reader.Read())
            switch (reader.Name)
            {
                case "property1":
                    property1 = reader.Value;
                    break;
                case "property2":
                    property2 = reader.Value;
                    break;
                case "property3":
                    property3 = reader.Value;
                    break;
            }
    }        
}

class Program
{
    static void Main(string[] args)
    {
        XmlSerializer mySer = new XmlSerializer(typeof(BaseClass), new Type [] {typeof(DerivedClass)});

        BaseClass exampleBaseClass;
        DerivedClass exampleDerivedClass = new DerivedClass();
        exampleDerivedClass.property1 = "Foo";
        exampleDerivedClass.property2 = "Bar";
        exampleDerivedClass.property3 = "Sth";

        exampleBaseClass = exampleDerivedClass;

        Console.WriteLine(exampleBaseClass.GetType());   // This prints "ConsoleApplication1.DerivedClass - and it's OK.
        StreamWriter sw = new StreamWriter("test.xml");
        mySer.Serialize(sw, exampleBaseClass);           // This creates file, that starts with xsi:type="DerivedClass" and contains all 3 properties - and it's OK.
        sw.Close();
        StreamReader sr = new StreamReader("test.xml");
        exampleBaseClass = (BaseClass)mySer.Deserialize(sr);
        Console.WriteLine(exampleBaseClass.GetType());   // This prints "ConsoleApplication1.DerivedClass - and it's OK. Everything works just great.
        Console.ReadKey();
    }
}
  1. This prints "ConsoleApplication1.DerivedClass - and it's OK.
  2. This creates file, that contains all 3 properties - and it's OK.
  3. This prints "ConsoleApplication1.BaseClass- and IT IS NOT OK. The resulting object contains only 2 properties.

The main question is: How to change definition of that simple classes?

Thanks for assistance.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
  • 1
    Perhaps you should look into the Attributes, which are able to control the output of the xml (btw. the DataContractSerializer does a better job, than default XmlSerializer). It could also be, that you have to add KnownTypes Attributes to your class. – TGlatzer Sep 25 '12 at 13:55
  • Sorry, but attributes are not enough in my application - and i want to learn, how to use ixmlserializable... – Jakub Szułakiewicz Sep 26 '12 at 09:50

0 Answers0