【问题标题】:How to make a serializable class that contains an instance of one class from a set of classes如何创建一个包含一组类中一个类的实例的可序列化类
【发布时间】:2013-01-14 21:18:10
【问题描述】:

在 .Net 4 或 4.5 中,您将如何设计一个包含一组类中的一个类的实例的可序列化类?例如,假设我有一个 Garage 类,它可以保存任何“车辆”类型类的实例,例如 Car、Boat、Motorcycle、Motorhome。但是车库只能保存其中一个类的实例。我尝试了几种不同的方法来做到这一点,但我的问题是使其可序列化。

这是一个起始示例,其中 Garage 类中的实例只有一个选项。您应该可以将其直接插入新的控制台应用程序并试用。

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

namespace Patterns
{
    [Serializable()]
    public class Garage
    {
        private Vehicle _MyVehicle;

        public Garage()
        {
        }
        public string GarageOwner { get; set; }
        public Vehicle MyVehicle
        {
            get { return _MyVehicle; }
            set { _MyVehicle = value; }
        }
    }

    [Serializable()]
    public class Vehicle
    {
        public string VehicleType { get; set; }
        public int VehicleNumber { get; set; }
    }

    class Serializer
    {
        static string _StartupPath = @"C:\Projects\Patterns\Data\";
        static string _StartupFile = "SerializerTest.xml";
        static string _StartupXML = _StartupPath + _StartupFile;

        static void Main(string[] args)
        {
            Console.Write("Press w for write. Press r for read:");
            ConsoleKeyInfo cki = Console.ReadKey(true);
            Console.WriteLine("Pressed: " + cki.KeyChar.ToString());
            if (cki.KeyChar.ToString() == "w")
            {
                Garage MyGarage = new Garage();
                MyGarage.GarageOwner = "John";
                MyGarage.MyVehicle = new Vehicle();
                MyGarage.MyVehicle.VehicleType = "Car";
                MyGarage.MyVehicle.VehicleNumber = 1234;
                WriteGarageXML(MyGarage);
                Console.WriteLine("Serialized");
            }
            else if (cki.KeyChar.ToString() == "r")
            {
                Garage MyGarage = ReadGarageXML();
                Console.WriteLine("Deserialized Garage owned by " +  MyGarage.GarageOwner);
            }
            Console.ReadKey();
        }
        public static void WriteGarageXML(Garage pInstance)
        {
            XmlSerializer writer = new XmlSerializer(typeof(Garage));
            using (FileStream file = File.OpenWrite(_StartupXML))
            {
                writer.Serialize(file, pInstance);
            }
        }
        public static Garage ReadGarageXML()
        {
            XmlSerializer reader = new XmlSerializer(typeof(Garage));
            using (FileStream input = File.OpenRead(_StartupXML))
            {
                return reader.Deserialize(input) as Garage;
            }
        }
    }
}

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    基于另一个SO article,这最终对我有用。 它可以干净地序列化和反序列化。使用这个例子,我可以设计一个对象的“树”,它可以选择使用什么。因此,这可以扩展为,一辆汽车可以有一个具有多种不同引擎类型类别的引擎和一个具有多种不同内饰类型的内饰......等等。

    代码通过添加以下语句开始工作,例如:[XmlInclude(typeof(Car))]

    但是如果有更好的方法,请告诉我!

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Xml;
    using System.Xml.Serialization;
    
    namespace Patterns
    {
        public class Garage
        {
            private Vehicle _MyVehicle;
    
            public Garage()
            {
            }
            public string GarageOwner { get; set; }
    
            public Vehicle MyVehicle
            {
                get { return _MyVehicle; }
                set { _MyVehicle = value; }
            }
        }
    
        [XmlInclude(typeof(Car))]
        [XmlInclude(typeof(Boat))]
        [XmlInclude(typeof(Motorcycle))]
        [XmlInclude(typeof(Motorhome))]
        public abstract class Vehicle
        {
            public string VehicleType { get; set; }
            public int VehicleNumber { get; set; }
        }
        public class Car : Vehicle
        {
            public int Doors { get; set; }
        }
        public class Boat : Vehicle
        {
            public int Engines { get; set; }
        }
        public class Motorcycle : Vehicle
        {
            public int Wheels { get; set; }
        }
        public class Motorhome : Vehicle
        {
            public int Length { get; set; }
        }
    
        class Serializer
        {
            static string _StartupPath = @"C:\Projects\Patterns\Data\";
            static string _StartupFile = "SerializerTest.xml";
            static string _StartupXML = _StartupPath + _StartupFile;
    
            static void Main(string[] args)
            {
                Console.Write("Press w for write. Press r for read:");
                ConsoleKeyInfo cki = Console.ReadKey(true);
                Console.WriteLine("Pressed: " + cki.KeyChar.ToString());
                if (cki.KeyChar.ToString() == "w")
                {
                    Garage MyGarage = new Garage();
                    MyGarage.GarageOwner = "John";
                    Car c = new Car();
                    c.VehicleType = "Lexus";
                    c.VehicleNumber = 1234;
                    c.Doors = 4;
                    MyGarage.MyVehicle = c;
                    WriteGarageXML(MyGarage);
                    Console.WriteLine("Serialized");
                }
                else if (cki.KeyChar.ToString() == "r")
                {
                    Garage MyGarage = ReadGarageXML();
                    Console.WriteLine("Deserialized Garage owned by " + MyGarage.GarageOwner);
                }
                Console.ReadKey();
            }
            public static void WriteGarageXML(Garage pInstance)
            {
                XmlSerializer writer = new XmlSerializer(typeof(Garage));
                using (FileStream file = File.OpenWrite(_StartupXML))
                {
                    writer.Serialize(file, pInstance);
                }
            }
            public static Garage ReadGarageXML()
            {
                XmlSerializer reader = new XmlSerializer(typeof(Garage));
                using (FileStream input = File.OpenRead(_StartupXML))
                {
                    return reader.Deserialize(input) as Garage;
                }
            }
        }    
    }
    

    【讨论】:

      【解决方案2】:

      要序列化可序列化类的序列,您可以使用通用列表实例。

      我生成了这个

      <?xml version="1.0"?>
      <Garage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <GarageOwner>John</GarageOwner>
        <MyVehicles>
          <Vehicle>
            <VehicleType>Car</VehicleType>
            <VehicleNumber>1234</VehicleNumber>
          </Vehicle>
          <Vehicle>
            <VehicleType>Boat</VehicleType>
            <VehicleNumber>56234</VehicleNumber>
          </Vehicle>
        </MyVehicles>
      </Garage>
      

      只需将 MyVehicle 转换为通用列表

      using System;
      using System.Collections.Generic;
      using System.IO;
      using System.Xml.Serialization;
      
      namespace Patterns
      {
          [Serializable()]
          public class Garage
          {
              public string GarageOwner { get; set; }
              public List<Vehicle> MyVehicles { get; set; }
          }
      
          [Serializable()]
          public class Vehicle
          {
              public string VehicleType { get; set; }
              public int VehicleNumber { get; set; }
          }
      
          class Serializer
          {
              static string _StartupPath = @"C:\temp\";
              static string _StartupFile = "SerializerTest.xml";
              static string _StartupXML = _StartupPath + _StartupFile;
      
              static void Main(string[] args)
              {
                  Console.Write("Press w for write. Press r for read:");
                  ConsoleKeyInfo cki = Console.ReadKey(true);
                  Console.WriteLine("Pressed: " + cki.KeyChar.ToString());
                  if (cki.KeyChar.ToString() == "w")
                  {
                      Garage MyGarage = new Garage();
                      MyGarage.GarageOwner = "John";
      
                      // Create some vehicles
                      var myVehicle1 = new Vehicle();
                      myVehicle1.VehicleType = "Car";
                      myVehicle1.VehicleNumber = 1234;
      
                      var myVehicle2 = new Vehicle();
                      myVehicle2.VehicleType = "Boat";
                      myVehicle2.VehicleNumber = 56234;
      
                      // Create a new instance and add the vehicles
                      MyGarage.MyVehicles = new List<Vehicle>()
                      {
                          myVehicle1, 
                          myVehicle2
                      };
      
                      WriteGarageXML(MyGarage);
                      Console.WriteLine("Serialized");
                  }
                  else if (cki.KeyChar.ToString() == "r")
                  {
                      Garage MyGarage = ReadGarageXML();
                      Console.WriteLine("Deserialized Garage owned by " +  MyGarage.GarageOwner);
                  }
                  Console.ReadKey();
              }
              public static void WriteGarageXML(Garage pInstance)
              {
                  XmlSerializer writer = new XmlSerializer(typeof(Garage));
                  using (FileStream file = File.OpenWrite(_StartupXML))
                  {
                      writer.Serialize(file, pInstance);
                  }
              }
              public static Garage ReadGarageXML()
              {
                  XmlSerializer reader = new XmlSerializer(typeof(Garage));
                  using (FileStream input = File.OpenRead(_StartupXML))
                  {
                      return reader.Deserialize(input) as Garage;
                  }
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-07
        • 2020-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-02
        • 2023-03-16
        • 2020-09-21
        相关资源
        最近更新 更多