当前位置: 首页 > news >正文

C#——XML序列化

开发环境

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 网络安全服务基础Windows--第9节-DNS部署与安全
  • 使用卫星仿真软件STK的一些应用和思考(星地链路、星间链路)
  • Java JVM 垃圾回收算法详解
  • JS基础学习笔记
  • JAVA毕业设计168—基于Java+Springboot+vue3的高校就业管理系统(源代码+数据库+14000字论文+开题+PPT)
  • 数据结构(1)
  • shell脚本编写之流程控制
  • 《NLP自然语言处理》—— 关键字提取之TF-IDF算法
  • 单片机开发过程中经常会遇到什么问题?
  • 幼儿园数字化探索:从入园适应到全面启智
  • 电镀车间氢气浓度在线监测:智能预警,守护生产安全线
  • 【数据集】RadioML2016.10a(RML2016.10a)
  • 实战项目:俄罗斯方块(七)
  • 传统CV算法——边缘算子与图像金字塔算法介绍
  • 浙大数据结构:01-复杂度1 最大子列和问题
  • 自己简单写的 事件订阅机制
  •  D - 粉碎叛乱F - 其他起义
  • jquery ajax学习笔记
  • magento 货币换算
  • npx命令介绍
  • Python_OOP
  • 从输入URL到页面加载发生了什么
  • 读懂package.json -- 依赖管理
  • 排序算法之--选择排序
  • 实现菜单下拉伸展折叠效果demo
  • 使用API自动生成工具优化前端工作流
  • 小程序button引导用户授权
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  •  一套莫尔斯电报听写、翻译系统
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • ​探讨元宇宙和VR虚拟现实之间的区别​
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #QT(智能家居界面-界面切换)
  • (1)bark-ml
  • (NSDate) 时间 (time )比较
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (三)终结任务
  • (十八)Flink CEP 详解
  • (四)汇编语言——简单程序
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • (转)重识new
  • .bat文件调用java类的main方法
  • .gitignore文件忽略的内容不生效问题解决
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .NET+WPF 桌面快速启动工具 GeekDesk
  • .Net6 Api Swagger配置
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • .NET应用架构设计:原则、模式与实践 目录预览
  • .so文件(linux系统)