【问题标题】:De-/serialization with a list of objects使用对象列表进行反序列化
【发布时间】:2017-03-10 06:17:40
【问题描述】:

我尝试在一个 XML 文件中保存和读取多个对象。

函数序列化不适用于我现有的列表,但我不知道为什么。我已经尝试编译它,但我得到一个错误,说该方法需要一个对象引用。

程序.cs:

    class Program
    {
        static void Main(string[] args)
        {
            List<Cocktail> lstCocktails = new List<Cocktail>();
            listCocktails.AddRange(new Cocktail[]
            {
                new Cocktail(1,"Test",true,true,
                new Cocktail(1, "Test4", true, true, 0)
        });


            Serialize(lstCocktails);

        }

        public void Serialize(List<Cocktail> list)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(List<Cocktail>));
            using (TextWriter writer = new StreamWriter(@"C:\Users\user\Desktop\MapSample\bin\Debug\ListCocktail.xml"))
            {
                serializer.Serialize(writer, list);
            }
        }

        private void DiserializeFunc()
        {
            var myDeserializer = new XmlSerializer(typeof(List<Cocktail>));
            using (var myFileStream = new FileStream(@"C:\Users\user\Desktop\MapSample\bin\Debug\ListCocktail.xml", FileMode.Open))
            {
                ListCocktails = (List<Cocktail>)myDeserializer.Deserialize(myFileStream);
            }
        }

鸡尾酒.cs:

    [Serializable()]
    [XmlRoot("locations")]
    public class Cocktail
    {

        [XmlElement("id")]
        public int CocktailID { get; set; }
        [XmlElement("name")]
        public string CocktailName { get; set; }
        [XmlElement("alc")]
        public bool alcohol { get; set; }
        [XmlElement("visible")]
        public bool is_visible { get; set; }
        [XmlElement("counter")]
        public int counter { get; set; }
        private XmlSerializer ser;

        public Cocktail() {
            ser = new XmlSerializer(this.GetType());
        }
        public Cocktail(int id, string name, bool alc,bool vis,int count)
        {
            this.CocktailID = id;
            this.CocktailName = name;
            this.alcohol = alc;
            this.is_visible = vis;
            this.counter = count;
        }
    }
}

我还认为我把 DiserializeFunc() 搞砸了。

【问题讨论】:

  • 如果您可以发布您收到的序列化错误,这将有所帮助。通过分析inner errors in a try catch 来尝试理解错误也是明智的。也可以尝试关注this tutorial on list serialization
  • 现在有什么问题?你没有在帖子里提到
  • 旁注:请避免使用与问题无关的文字,例如“新来的”、“谢谢”、“我是 Bob the Third”(或任何其他签名)。相反,请确保帖子中提供的代码遵循minimal reproducible example 准则以及帖子中存在的所有必要信息,例如输入/输出/错误消息。

标签: c# xml serialization deserialization


【解决方案1】:

您非常接近正确实现 Cocktail 类,但我认为您对如何序列化列表感到困惑。您对 Cocktail 对象类的实现完全没问题,只需去掉与列表相关的函数即可。

using System;
using System.Xml.Serialization;

namespace Serialization_Help
{
    [Serializable()]
    [XmlRoot("locations")]
    public class Cocktail
    {

        [XmlElement("id")]
        public int CocktailID { get; set; }
        [XmlElement("name")]
        public string CocktailName { get; set; }
        [XmlElement("alc")]
        public bool alcohol { get; set; }
        [XmlElement("visible")]
        public bool is_visible { get; set; }
        [XmlElement("counter")]
        public int counter { get; set; }
        public Cocktail() {

        }
        public Cocktail(int id, string name, bool alc, bool vis, int count)
        {
            this.CocktailID = id;
            this.CocktailName = name;
            this.alcohol = alc;
            this.is_visible = vis;
            this.counter = count;
        }
    }
}

现在在您的新函数中,您想直接序列化列表。

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

namespace Serialization_Help
{
    class Program {
        static void Main(string[] args) {
            List<Cocktail> list = new List<Cocktail> {
                new Cocktail(01, "rum and coke", true, true, 5),
                new Cocktail(02, "water on the rocks", false, true, 3)
            };
            Serialize(list);
            List<Cocktail> deserialized = DiserializeFunc();
        }

        public static void Serialize(List<Cocktail> list) {

            XmlSerializer serializer = new XmlSerializer(typeof(List<Cocktail>));
            using (TextWriter writer = new StreamWriter(Directory.GetCurrentDirectory() + @"\ListCocktail.xml")) serializer.Serialize(writer, list);
        }

        private static List<Cocktail> DiserializeFunc() {
            var myDeserializer = new XmlSerializer(typeof(List<Cocktail>));
            using (var myFileStream = new FileStream(Directory.GetCurrentDirectory() + @"\ListCocktail.xml", FileMode.Open)) return (List<Cocktail>)myDeserializer.Deserialize(myFileStream);
        }
    }
}

这样做应该会正确打印出以下 .xml 输出:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfCocktail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Cocktail>
    <id>1</id>
    <name>rum and coke</name>
    <alc>true</alc>
    <visible>true</visible>
    <counter>5</counter>
  </Cocktail>
  <Cocktail>
    <id>2</id>
    <name>water on the rocks</name>
    <alc>false</alc>
    <visible>true</visible>
    <counter>3</counter>
  </Cocktail>
</ArrayOfCocktail>

请记住,我没有为文件提供任何标准安全或空检查的实现。您必须使用File.Exists(...) (see here for File.Exists implementation) 检查文件是否存在,并实施正确的trycatch 案例,以及如果遇到序列化或输入/输出错误,您的代码将选择做什么。

【讨论】:

  • 哇,感谢您的出色回答!这将帮助我作为我的程序的基础!如果它准备好使用你会得到一个鸡尾酒;):D
【解决方案2】:

你最好使用ExtendedXmlSerializer进行序列化和反序列化。

安装 您可以从nuget 安装 ExtendedXmlSerializer 或运行以下命令:

Install-Package ExtendedXmlSerializer

序列化:

ExtendedXmlSerializer serializer = new ExtendedXmlSerializer();
var list = new List<Cocktail>();
var xml = serializer.Serialize(list);

反序列化

var list = serializer.Deserialize<List<Cocktail>>(xml);

.NET 中的标准 XML 序列化器非常有限。

  • 不支持带有循环引用的类或带有接口属性的类的序列化,
  • 不支持字典,
  • 没有读取旧版XML的机制,
  • 如果您想创建自定义序列化程序,您的类必须继承自 IXmlSerializable。这意味着您的课程将不是 POCO 课程,
  • 不支持 IoC。

ExtendedXmlSerializer 可以做到这一点以及更多。

ExtendedXmlSerializer 支持 .NET 4.5 或更高版本以及 .NET Core。您可以将它与 WebApi 和 AspCore 集成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-10
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-12
    相关资源
    最近更新 更多