C#——XML序列化

news/2024/9/20 1:27:46/ 标签: c#

开发环境

VS2022

.net core 6.0

序列化概念

序列化是将内存中的对象或者对象图(一组相互引用的对象)拉平为一个可以保存或进行传输的字节流,或者XML节点。反序列化正好相反,它把数据流重新构造成内存中的一个对象或者对象图。

序列化用途

序列化和反序列化通常用于:

· 通过网络或程序边界传输对象

· 在文件或者数据库中保存对象

此外,它还可以用于深度克隆对象。而数据契约和XML序列化引擎也可以当作通用工具,用于加载和保存已知结构的XML文件。

可序列化的项

  • 公共类的公共读/写属性和字段。

  • 执行 ICollection 或 IEnumerable 的类 。

  • XmlElement 对象。

  • XmlNode 对象。

  • DataSet 对象。

序列化常用特性

XmlRoot——申明根结点,如: [XmlRoot(ElementName = "Root")]

XmlIgnore——忽悠某个属性或字段,如 :[XmlIgnore] public int Id;

XmlInclude——是否包含某个类,如:[XmlInclude(typeof(Results))]

XmlArray——申明集合

XmlArrayItem——申明集合中元素,如下:

        [XmlArray("Targets", Namespace = "TwoPoint")][XmlArrayItem("Target", Namespace = "TwoPoint")]public Point[] Points { get; set; }

XML 序列化注意事项

使用 XmlSerializer 类时,应注意以下事项:

  • 序列化数据只包含数据本身和类的结构。 

  • 只能序列化公共属性和字段。 属性必须具有公共访问器(get 和 set 方法)。 

  • 类必须具有无参数构造函数才能被 XmlSerializer 序列化。

  • 方法不能被序列化。

  • 如下所述,如果实现 IEnumerable 或 ICollection 的类满足某些要求,XmlSerializer 则可以处理这些类 。

    实现 IEnumerable 的类必须实现采用单个参数的公共 Add 方法 。

    实现 ICollection 的类(如 CollectionBase)必须具有采用整型的公共“Item”索引属性(在 C# 中为索引器),而且它必须有一个“integer”类型的公共“Count”属性 。 传递给 Add 方法的参数必须与从“Item”属性返回的类型相同,或者为此类型的基之一 。

常见错误及解决办法

以下为愚初次使用时遇到的一引问题,及解决办法:

 不同命名空间下的相同类名下异常

InvalidOperationException: Types 'WpfApp.Xml.Results.Target' and 'WpfApp.Xml.PlanInfo.Target' both use the XML type name, 'Target', from namespace ''. Use XML attributes to specify a unique XML name and/or namespace for the type.

解决办法:如上黄色字体,即为序列化的对象添加Namespace,如下

    [XmlType(Namespace = "WpfApp.Xml.Results")]public class Target{/// <summary>/// 编号/// </summary>[XmlAttributeAttribute(AttributeName = "id")]public double NO { get; set; }}

注意仅需要添加Namespace即可,不需要添加TypeName。

很多文章提到应该添加TypeName和Namespace,如下的操作方式:

    [XmlType(TypeName = "PTarget", Namespace = "WpfApp.Xml.Info")]public class Target{/// <summary>/// 编号/// </summary>[XmlAttributeAttribute(AttributeName = "id")]public double NO { get; set; }}

但若添加了TypeName会导致你后一个不同NameSpace下的类改为你Namespace中设置的名称。

非集合属性或字段添加了集合特性

InvalidOperationException: For non-array types, you may use the following attributes: XmlAttribute, XmlText, XmlElement, or XmlAnyElement.

集合属性或字段添加了 XmlElement

集合不能使用它,否则会导致它的子元素全部显示为Targets,而应该如下:

        [XmlArray("Targets")]
        [XmlArrayItem("Target")]
        public Point[] Points { get; set; }

XmlArray指定了集合Points在Xml中的显示名称,

XmlArrayItem指定了集合中元素在Xml中的显示名称。

对象序列化与反序列化常用代码

对象序列化为XML文件

        /// <summary>/// 序列化对象为XML文件/// </summary>internal static void XmlSerializer<T>(string fileName, T t) where T : new(){try{XmlSerializer serializer = new(typeof(SerializationWrapper));using TextWriter tr = new StreamWriter(fileName, false, Encoding.UTF8);// 序列化包装类serializer.Serialize(tr, t);tr.Close();tr.Dispose();}catch (Exception ex){Debug.WriteLine("序列化失败");Exception exception = new("序列化失败");throw exception;}}

xml文件反序化为对象

        /// <summary>/// 反序列化XML文件为对象/// </summary>/// <param name="fileName">文件名</paraminternal static T XmlDeserialize<T>(string fileName) where T : new()  {using FileStream s = File.OpenRead(fileName);// 创建包装类的实例并添加对象XmlSerializer xs = new(typeof(T));T sw = (T)xs.Deserialize(s);return sw;}

上述代码最好还是添加上try……catch……以进行错误处理。

对象序列化为字符串

        /// <summary>/// 将对象序列化为XML字符串/// </summary>/// <typeparam name="T">需要序列化的类型</typeparam>/// <param name="t">序列化的对象实例</param>/// <returns>序列化对象的字符串</returns>internal static string Object2XmlStringSerializer<T>(T t) where T : new(){try{// 创建包装类的实例并添加对象T wrapper = t;// 创建XmlSerializer的实例,指定根元素名称XmlSerializer serializer = new(typeof(T));// 使用StringWriter来捕获序列化后的XML内容using (StringWriter stringWriter = new()){serializer.Serialize(stringWriter, wrapper);string xmlContent = stringWriter.ToString();Debug.WriteLine(xmlContent);return xmlContent;}}catch (Exception ex){Debug.WriteLine("序列化失败");Exception exception = new("序列化失败");throw exception;}}

若需要指定编码方式,那么就需要转化为数据流,然后指定相应的编码方式后再读取,如下:

                using (MemoryStream memoryStream = new ()){using (StreamWriter streamWriter = new (memoryStream, Encoding.UTF8)){serializer.Serialize(streamWriter, t);streamWriter.Flush();memoryStream.Position = 0;using (StreamReader streamReader = new (memoryStream, Encoding.UTF8)){string xmlContent = streamReader.ReadToEnd();Debug.WriteLine(xmlContent);return xmlContent;}}}

其实没有必要指定编码方式,从测试结果来看,反序列化时并不需要指定相应的编码方式,也可以正确进行解码。

xml字符串反序化为对象

/// <summary>
/// 将XML字符串反序列化为对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xmlString"></param>
/// <returns></returns>
internal static T XmlStringDeserializer<T>(string xmlString) where T : new()
{// 使用StringReader包装XML字符串using StringReader stringReader = new(xmlString);try{XmlSerializer serializer = new(typeof(T));// 反序列化XML字符串T root = (T)serializer.Deserialize(stringReader);return root;}catch (Exception ex){throw ex;}
}

参考资料

《C# 核心技术指南(原书第7版)》

XML 序列化详细信息 - .NET | Microsoft Learn


http://www.ppmy.cn/news/1523460.html

相关文章

vue3 a-modal点击弹窗外让弹窗不关闭,且每次关闭置空输入框数据。

vue3 a-modal点击弹窗外让弹窗不关闭&#xff0c;且每次关闭置空输入框数据。 点击弹窗区域外不关闭弹窗&#xff1a;:maskClosable"false"cancel"handleClose"方法关闭modal置空数据 点击弹窗区域外不关闭弹窗&#xff1a;:maskClosable“false” cancel…

Java中Date类型上的注解

在日常开发中&#xff0c;涉及到日期时间类型Date和常用的注解DateTimeFormat和JsonFormat java.util.Date; org.springframework.format.annotation.DateTimeFormat; com.fasterxml.jackson.annotation.JsonFormat; 一 Date类型字段不使用注解 Data AllArgsConstructor N…

FPGA——VGA协议

VGA协议 VGA简介接口及引脚定义显示原理显示电路原理VGA协议电压标准数字信号转化标准模拟信号方案数字信号时序标准 模块设计 VGA简介 VGA&#xff0c;英文全称“Video Graphics Array”&#xff0c;译为视频图形阵列&#xff0c;是一种使用模拟信号进行视频传输的标准协议&a…

ElementUI2.x El-Select组件 处理使用远程查找时下拉箭头丢失问题

1、问题描述 elementui2.x版本使用el-select组件的remote-method远程查找时&#xff0c;发现下拉箭头丢失了&#xff0c;且当查找接口返回数据为空时&#xff0c;也不会展开下拉列表来显示暂无数据提示&#xff1b; 2、源码解析 官网使用示例&#xff1a; <template>…

Java设计模式【命令模式】-行为型

1. 介绍 命令模式&#xff08;Command Pattern&#xff09; 是一种行为型设计模式&#xff0c;它将一个请求封装为一个对象&#xff0c;从而使我们可以用不同的请求对客户端进行参数化&#xff0c;并且支持请求的排队、记录日志以及撤销、重做等功能。命令模式将请求的发送者与…

JavaScript高级——函数

1、函数的含义&#xff1a; ① 实现特定功能的n条语句的封装体。 ② 只有函数是可以执行的&#xff0c;其他类型的数据不能执行。 2、为什么要用函数&#xff1f; ① 提高代码复用 ② 便于阅读交流 3、如何定义函数&#xff1f; ① 函数声明 ② 表达式 4、如何调用&#…

vue3+ant design vue实现文件上传(阿里云oss)~

1、效果图 2、自定义上传 <a-upload v-model:file-list"fileList" name"导入员工" action"" :customRequest"upDown" :beforeUpload"beforeUpload" :onChange"handleChange" remove"removeFile" ac…

使用MATLAB进行动力学分析与可视化

目录 一、动力学与MATLAB概述 二、动力学系统的建模 1. 简谐振子 2. 单摆 三、动力学系统的仿真 1. 使用ode45求解简谐振子 2. 使用ode45求解单摆 四、动力学结果的可视化 1. 二维曲线图 2. 相空间图 3. 三维曲面图 4. 动画制作 五、复杂动力学系统的建模与仿真 1…

数据恢复的基石:MySQL中的存储管理策略

在企业数据管理中&#xff0c;数据恢复的存储管理是确保数据安全和业务连续性的关键环节。MySQL作为广泛使用的数据库系统&#xff0c;其数据恢复的存储管理对于优化备份存储、提高恢复效率和保障数据完整性至关重要。本文将深入探讨如何在MySQL中实现数据恢复的存储管理&#…

OpenCV仿射变换和透视变换函数(C++)

文章目录 引言图像仿射变换 warpAffine()图像的旋转仿射变换 透视变换 warpPerspective()透视变换例子参考文献 **仿射变换相关函数** cv::transform()&#xff1a;对一组点进行仿射变换 cv::warpAffine()&#xff1a;对整幅图像进行仿射变换 cv::getAffineTransform()&#xf…

Qt篇——Qt在msvc编译下提示“C2001:常量中有换行符“的错误

在pro文件中添加以下配置即可&#xff1a; msvc{QMAKE_CFLAGS /utf-8QMAKE_CXXFLAGS /utf-8 }

Flask中的上下文(Context)

Flask中的上下文&#xff08;Context&#xff09;是一个核心概念&#xff0c;它对于理解和使用Flask框架进行Web开发至关重要。上下文在编程中通常指的是程序执行到某一时刻时&#xff0c;环境所提供的一系列状态信息&#xff0c;这些状态信息可以是变量、函数、类等&#xff0…

[Redis] Redis中的String类型

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

【机器学习】12. 线性回归 Residual 残差系数 R方

Sum of Squares Total (SST) 单个数据点&#xff08;观测值&#xff09;于响应变量的均值差的平方和。 Sum of Squares Regression (SSR) 预测值ŷi与响应变量均值差的平方和。 Sum of Squares Error (SSE) 预测值ŷi与观测值差的平方和。 R 2 1 − S S E / S S T S S R / …

前端技术(七)——less 教程

一、less简介 1. less是什么&#xff1f; less是一种动态样式语言&#xff0c;属于css预处理器的范畴&#xff0c;它扩展了CSS语言&#xff0c;增加了变量、Mixin、函数等特性&#xff0c;使CSS 更易维护和扩展LESS 既可以在 客户端 上运行 &#xff0c;也可以借助Node.js在服…

一台笔记本电脑的硬件都有哪些以及对应的功能

一台笔记本电脑的硬件通常包括多个关键组件&#xff0c;这些组件共同协作&#xff0c;确保电脑的正常运行。以下是笔记本电脑的主要硬件及其功能&#xff1a; 1. 中央处理器&#xff08;CPU&#xff09; 功能&#xff1a;CPU 是电脑的“大脑”&#xff0c;负责处理所有的计算…

bit-fields 生成macros

‌Bit-Fields Macros定义‌ Bit-fields macros是在C或C语言中&#xff0c;‌利用宏定义&#xff08;‌macros&#xff09;‌来方便地创建和操作位字段&#xff08;‌bit-fields&#xff09;‌的一种方式。‌位字段常用于节省内存&#xff0c;‌通过在一个字节中打包多个布尔值或…

【PHP小课堂】简单入门PHP中的过滤器相关函数

简单入门PHP中的过滤器相关函数 一般在业务开发中&#xff0c;我们对于一些参数数据的过滤大部分还是使用传统的 if 以及正则进行判断过滤。但其实 PHP 中也提供了一些过滤器&#xff0c;可以帮助我们方便地进行数据的过滤筛选以及部分替换操作。今天我们就来简单的学习一下这些…

设计模式之状态模式 (C++ 实现)

设计模式是软件开发中的一项重要技能&#xff0c;它提供了一种通用的解决方案以应对不同的设计问题。状态模式是一种行为型设计模式&#xff0c;适用于对象在不同状态下表现出不同的行为。通过实现状态模式&#xff0c;可以让代码更清晰、更易扩展与维护。本文将通过C实现状态模…

【开发工具】Maven Dependency Helper:IntelliJ IDEA的贴心助手,助力梳理依赖关系

一、引言 在Java项目开发过程中&#xff0c;依赖管理是一个至关重要的环节。Maven作为一个优秀的构建工具&#xff0c;已经成为了Java项目标配。然而&#xff0c;在管理项目依赖时&#xff0c;我们常常会遇到各种问题&#xff0c;如依赖冲突、依赖版本不兼容等。为了让开发者更…