如何使包含一个类的实例从一组类可序列化类 [英] How to make a serializable class that contains an instance of one class from a set of classes

查看:71
本文介绍了如何使包含一个类的实例从一组类可序列化类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在.NET 4中,或4.5,你会怎么设计包含一个类的实例从一组类可序列化类?举例来说,假设我有一个车库类,它可以保存任何车式的类的实例,比如汽车,小船,摩托车,房车。但车库只能容纳这些类的一个实例。我曾尝试这样做了一些不同的方式,但我的问题是使序列化。

下面是一个起始例子中只有一个在车库类的实例选项。你应该能够将其右转入一个新的控制台应用程序和尝试。

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.IO;
使用的System.Xml;
使用的System.Xml.Serialization;

命名空间模式
{
    [序列化()]
    公共类停车库
    {
        私家车_MyVehicle;

        公共停车场()
        {
        }
        公共字符串GarageOwner {获得;组; }
        大众汽车MyVehicle
        {
            {返回_MyVehicle; }
            集合{_MyVehicle =价值; }
        }
    }

    [序列化()]
    公共类车辆
    {
        公共字符串VehicleType {获得;组; }
        公众诠释VehicleNumber {获得;组; }
    }

    一流的串行
    {
        静态字符串_StartupPath = @C:\项目\模式\ DATA \;
        静态字符串_StartupFile =SerializerTest.xml;
        静态字符串_StartupXML = _StartupPath + _StartupFile;

        静态无效的主要(字串[] args)
        {
            Console.Write(preSS w代表写preSS r代表读:);
            ConsoleKeyInfo CKI = Console.ReadKey(真正的);
            Console.WriteLine(pressed:+ cki.KeyChar.ToString());
            如果(cki.KeyChar.ToString()==瓦特)
            {
                车库MyGarage =新的车库();
                MyGarage.GarageOwner =约翰;
                MyGarage.MyVehicle =新车();
                MyGarage.MyVehicle.VehicleType =车;
                MyGarage.MyVehicle.VehicleNumber = 1234;
                WriteGarageXML(MyGarage);
                Console.WriteLine(序列化);
            }
            否则如果(cki.KeyChar.ToString()==R)
            {
                车库MyGarage = ReadGarageXML();
                Console.WriteLine(+ MyGarage.GarageOwner反序列化车库归);
            }
            Console.ReadKey();
        }
        公共静态无效WriteGarageXML(车库pInstance)
        {
            XmlSerializer的作家=新的XmlSerializer(typeof运算(车库));
            使用(的FileStream文件= File.OpenWrite(_StartupXML))
            {
                writer.Serialize(文件,pInstance);
            }
        }
        公共静态车库ReadGarageXML()
        {
            XmlSerializer的读者=新的XmlSerializer(typeof运算(车库));
            使用(的FileStream输入= File.OpenRead(_StartupXML))
            {
                返回reader.Deserialize(输入)作为车库;
            }
        }
    }
}
 

解决方案

根据另一个<一href="http://stackoverflow.com/questions/10236014/xml-serialization-of-class-which-has-a-member-extended-from-an-abstract-type?rq=1">SO文章,这是最终为我工作。 它可以序列化和反序列化干净。用这个例子,我可以设计出有什么用选择对象的树。因此,这可以扩大,一个汽车可以有几种不同的发动机类型类之一发动机和若干不同类型的内部的一个内部...等

在code开始通过添加以下语句类似的工作:[XmlInclude(typeof运算(车))]

但请让我知道如果有更好的方法!

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.IO;
使用的System.Xml;
使用的System.Xml.Serialization;

命名空间模式
{
    公共类停车库
    {
        私家车_MyVehicle;

        公共停车场()
        {
        }
        公共字符串GarageOwner {获得;组; }

        大众汽车MyVehicle
        {
            {返回_MyVehicle; }
            集合{_MyVehicle =价值; }
        }
    }

    [XmlInclude(typeof运算(车))]
    [XmlInclude(typeof运算(船))]
    [XmlInclude(typeof运算(摩托车))]
    [XmlInclude(typeof运算(房车))]
    公共抽象类车辆
    {
        公共字符串VehicleType {获得;组; }
        公众诠释VehicleNumber {获得;组; }
    }
    公共类车:车辆
    {
        公众诠释门{获得;组; }
    }
    公共类船:车辆
    {
        公众诠释引擎{获得;组; }
    }
    公共类摩托车:汽车
    {
        公众诠释轮{获得;组; }
    }
    公共类房车:汽车
    {
        公众诠释长度{获得;组; }
    }

    一流的串行
    {
        静态字符串_StartupPath = @C:\项目\模式\ DATA \;
        静态字符串_StartupFile =SerializerTest.xml;
        静态字符串_StartupXML = _StartupPath + _StartupFile;

        静态无效的主要(字串[] args)
        {
            Console.Write(preSS w代表写preSS r代表读:);
            ConsoleKeyInfo CKI = Console.ReadKey(真正的);
            Console.WriteLine(pressed:+ cki.KeyChar.ToString());
            如果(cki.KeyChar.ToString()==瓦特)
            {
                车库MyGarage =新的车库();
                MyGarage.GarageOwner =约翰;
                汽车C =新车();
                c.VehicleType =雷克萨斯;
                c.VehicleNumber = 1234;
                c.Doors = 4;
                MyGarage.MyVehicle = C;
                WriteGarageXML(MyGarage);
                Console.WriteLine(序列化);
            }
            否则如果(cki.KeyChar.ToString()==R)
            {
                车库MyGarage = ReadGarageXML();
                Console.WriteLine(+ MyGarage.GarageOwner反序列化车库归);
            }
            Console.ReadKey();
        }
        公共静态无效WriteGarageXML(车库pInstance)
        {
            XmlSerializer的作家=新的XmlSerializer(typeof运算(车库));
            使用(的FileStream文件= File.OpenWrite(_StartupXML))
            {
                writer.Serialize(文件,pInstance);
            }
        }
        公共静态车库ReadGarageXML()
        {
            XmlSerializer的读者=新的XmlSerializer(typeof运算(车库));
            使用(的FileStream输入= File.OpenRead(_StartupXML))
            {
                返回reader.Deserialize(输入)作为车库;
            }
        }
    }
}
 

In .Net 4 or 4.5, how would you design a serializable class that contains an instance of one class from a set of classes? For instance, suppose I have a Garage class, which can hold an instance of any "vehicle" type classes, say Car, Boat, Motorcycle, Motorhome. But the Garage can only hold an instance of one of those classes. I have tried a few different ways of doing this, but my problem is to make it serializable.

Here is a starting example where there is only one option for the instance in the Garage class. You should be able to plug it right into a new console app and try it.

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

解决方案

Based on another SO article, this is what finally worked for me. It can serialize and deserialize cleanly. Using this example, I can design a "tree" of objects which have options for what is used. So this could be extended that a Car can have one Engine of several different Engine type classes and one Interior of several different Interior types... and so on.

The code began to work by adding the statements below like: [XmlInclude(typeof(Car))]

But please let me know if there are better ways!

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

这篇关于如何使包含一个类的实例从一组类可序列化类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆