10

.Net 4 または 4.5 では、一連のクラスから 1 つのクラスのインスタンスを含むシリアル化可能なクラスをどのように設計しますか? たとえば、Car、Boat、Motorhome、Motorhome などの「乗り物」タイプのクラスのインスタンスを保持できる Garage クラスがあるとします。しかし、ガレージはこれらのクラスの 1 つのインスタンスしか保持できません。私はこれを行うためにいくつかの異なる方法を試しましたが、私の問題はシリアライズ可能にすることです。

これは、Garage クラスのインスタンスのオプションが 1 つしかない開始例です。新しいコンソール アプリにプラグインして試すことができるはずです。

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の記事に基づいて、これが最終的に私にとってうまくいきました。きれいにシリアライズおよびデシリアライズできます。この例を使用して、何を使用するかのオプションを持つオブジェクトの「ツリー」を設計できます。したがって、これは、車が複数の異なるエンジン タイプ クラスの 1 つのエンジンと、複数の異なるインテリア タイプの 1 つのインテリアを持つことができるように拡張できます。

[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 に答える