使用IXmlSerializable对派生类进行C#序列化

时间:2012-09-25 13:35:17

标签: c# .net xml-serialization polymorphism ixmlserializable

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

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

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

我们需要:

  1. 创建DerivedClass的实例
  2. 将其分配给BaseClass类型的变量
  3. 将该变量序列化为XML文件
  4. 将该文件反序列化为BaseClass类型的变量
  5. 该变量应包含DerivedClass类型的对象
  6. 第一个示例程序使用“内置”序列化 - 并且工作正常。

    但是我希望对序列化过程有更多的控制(使用IXmlSerializable接口) AND 达到同样的效果。

    第一个例子:

    [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 - 它没关系。
    4. 第二个例子:

      [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-并且它不合适。结果对象只包含2个属性。
      4. 主要问题是: 如何更改简单类的定义?

        感谢您的帮助。

0 个答案:

没有答案