2

我会尽量让我的问题尽可能简单。下面是 2 个示例程序来演示它。如果您需要分析它,您可以将其复制并粘贴到 Visual Studio 中。

随意评论和纠正我的英语。希望你能理解我。

我的目标是: 我们有 2 个类 - BaseClass 和 DerivedClass。

我们要:

  1. 创建 DerivedClass 的实例
  2. 将其分配给 BaseClass 类型的变量
  3. 将该变量序列化为 XML 文件
  4. 将该文件反序列化为 BaseClass 类型的变量
  5. 该变量应包含 DerivedClass 类型的对象

第一个示例程序使用“内置”序列化 - 并且工作正常。

但我想对序列化过程有更多的控制(使用 IXmlSerializable 接口)达到相同的效果。

第一个例子:

[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. 这将打印“ConsoleApplication1.DerivedClass - 没关系。
  2. 这将创建包含所有 3 个属性的文件 - 没关系。
  3. 这将打印“ConsoleApplication1.DerivedClass - 没关系。

第二个例子:

[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. 这将打印“ConsoleApplication1.DerivedClass - 没关系。
  2. 这将创建包含所有 3 个属性的文件 - 没关系。
  3. 这将打印 "ConsoleApplication1.BaseClass- and IT IS NOT OK。生成的对象仅包含 2 个属性。

主要问题是: 如何更改简单类的定义?

感谢您的帮助。

4

0 回答 0