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;
            }
        }
    }
}
4

2 回答 2

6

基于另一篇 SO 文章,这最终对我有用。它可以干净地序列化和反序列化。使用此示例,我可以设计一个对象“树”,其中包含所用对象的选项。因此,这可以扩展为,一辆汽车可以有一个具有几种不同发动机类型类别的发动机和一个具有几种不同内饰类型的内饰……等等。

代码通过添加以下语句开始工作,例如:[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;
            }
        }
    }    
}
于 2013-01-14T21:57:04.877 回答
4

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

我生成了这个

<?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;
            }
        }
    }
}
于 2013-01-14T21:30:04.380 回答