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

Unity_数据持久化_IXmlSerializable接口

Unity数据持久化

三、XML数据持久化

3.5 IXmlSerializable接口

3.5.1 IXmlSerializable接口基础概念

什么是IXmlSerializable接口:
IXmlSerializable 是.NET框架提供的一个接口,允许类自定义XML序列化和反序列化的过程。当默认的XML序列化行为无法满足需求时,可以实现这个接口来完全控制XML的读写过程。

接口定义:

public interface IXmlSerializable
{XmlSchema GetSchema();void ReadXml(XmlReader reader);void WriteXml(XmlWriter writer);
}

核心方法说明:

  • GetSchema():返回XML架构定义,通常返回null
  • ReadXml(XmlReader reader):自定义XML反序列化过程
  • WriteXml(XmlWriter writer):自定义XML序列化过程
3.5.2 实现IXmlSerializable接口

基本实现结构:

using System.Xml.Serialization;
using System.Xml;
using System.Xml.Schema;public class TextData : IXmlSerializable
{public string text = "gsffs";public int age;public List<string> list;public int[] array = new int[3] { 1, 2, 3 };// 实现IXmlSerializable接口public XmlSchema GetSchema(){return null; // 通常返回null}public void ReadXml(XmlReader reader){// 自定义反序列化逻辑}public void WriteXml(XmlWriter writer){// 自定义序列化逻辑}
}
3.5.3 自定义XML序列化(WriteXml方法)

WriteXml方法用于控制对象如何序列化为XML格式。有三种主要的写入方式:

1. 写入属性(Attribute)

public void WriteXml(XmlWriter writer)
{// 将数据作为XML元素的属性写入writer.WriteAttributeString("text", text);writer.WriteAttributeString("age", age.ToString());
}

生成的XML格式:

<TextData text="gsffs" age="25" />

2. 写入元素节点(Element)

public void WriteXml(XmlWriter writer)
{// 将数据作为独立的XML元素写入writer.WriteElementString("text", text);writer.WriteElementString("age", age.ToString());
}

生成的XML格式:

<TextData><text>gsffs</text><age>25</age>
</TextData>

3. 写入包裹节点(复杂序列化)

public void WriteXml(XmlWriter writer)
{// 使用XmlSerializer进行复杂类型的序列化XmlSerializer ser = new XmlSerializer(typeof(string));// 写入text字段writer.WriteStartElement("text1");ser.Serialize(writer, text);writer.WriteEndElement();// 写入age字段XmlSerializer ser2 = new XmlSerializer(typeof(int));writer.WriteStartElement("age");ser2.Serialize(writer, age);writer.WriteEndElement();
}

生成的XML格式:

<TextData><text1>gsffs</text1><age>25</age>
</TextData>
3.5.4 自定义XML反序列化(ReadXml方法)

ReadXml方法用于控制如何从XML格式反序列化为对象。有三种主要的读取方式:

1. 读取属性(Attribute)

public void ReadXml(XmlReader reader)
{// 从XML元素的属性中读取数据age = int.Parse(reader.GetAttribute("age"));text = reader.GetAttribute("text");
}

2. 读取元素节点(Element)

public void ReadXml(XmlReader reader)
{// 方法1:手动控制读取过程reader.Read(); // 读取text节点reader.Read(); // 读取text包裹内容text = reader.Value;reader.Read(); // 读取text末节点reader.Read(); // 读取age节点reader.Read(); // 读取age包裹内容age = int.Parse(reader.Value);reader.Read(); // 读取age末节点
}

3. 使用循环读取多个元素

public void ReadXml(XmlReader reader)
{// 方法2:使用循环遍历所有元素while (reader.Read()){if (reader.NodeType == XmlNodeType.Element){switch (reader.Name){case "text":reader.Read();text = reader.Value;break;case "age":reader.Read();age = int.Parse(reader.Value);break;}}}
}

4. 读取包裹节点(复杂反序列化)

public void ReadXml(XmlReader reader)
{// 使用XmlSerializer进行复杂类型的反序列化XmlSerializer ser3 = new XmlSerializer(typeof(string));XmlSerializer ser4 = new XmlSerializer(typeof(int));reader.Read(); // 跳过根节点reader.ReadStartElement();text = (string)ser3.Deserialize(reader);reader.ReadEndElement();reader.Read();reader.ReadStartElement();age = (int)ser4.Deserialize(reader);reader.ReadEndElement();
}
3.5.5 完整的IXmlSerializable实现示例

基于您的代码的完整实现:

using UnityEngine;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Collections.Generic;/// <summary>
/// 自定义XML序列化的数据类
/// 实现IXmlSerializable接口以完全控制XML读写过程
/// </summary>
public class TextData : IXmlSerializable
{public string text = "gsffs";public int age;public List<string> list;public int[] array = new int[3] { 1, 2, 3 };/// <summary>/// 返回XML架构定义/// </summary>/// <returns>通常返回null</returns>public XmlSchema GetSchema(){return null;}/// <summary>/// 自定义XML反序列化过程/// </summary>/// <param name="reader">XML读取器</param>public void ReadXml(XmlReader reader){// 使用XmlSerializer进行复杂类型的反序列化XmlSerializer ser3 = new XmlSerializer(typeof(string));XmlSerializer ser4 = new XmlSerializer(typeof(int));reader.Read(); // 跳过根节点reader.ReadStartElement();text = (string)ser3.Deserialize(reader);reader.ReadEndElement();reader.Read();reader.ReadStartElement();age = (int)ser4.Deserialize(reader);reader.ReadEndElement();}/// <summary>/// 自定义XML序列化过程/// </summary>/// <param name="writer">XML写入器</param>public void WriteXml(XmlWriter writer){// 使用XmlSerializer进行复杂类型的序列化XmlSerializer ser = new XmlSerializer(typeof(string));writer.WriteStartElement("text1");ser.Serialize(writer, text);writer.WriteEndElement();XmlSerializer ser2 = new XmlSerializer(typeof(int));writer.WriteStartElement("age");ser2.Serialize(writer, age);writer.WriteEndElement();}
}/// <summary>
/// IXmlSerializable接口测试类
/// 演示如何使用自定义XML序列化
/// </summary>
public class XmlSerilizef : MonoBehaviour
{void Start(){// 设置存储路径string path = Application.persistentDataPath + "/TextData.xml";print("存储路径: " + path);// 创建测试数据TextData textData = new TextData();textData.list = new List<string>() { "1", "2", "3" };textData.age = 25;// 序列化对象到XML文件XmlSerializer ser444 = new XmlSerializer(typeof(TextData));using (StreamWriter sw = new StreamWriter(path)){ser444.Serialize(sw, textData);}// 从XML文件反序列化对象TextData textData2;using (StreamReader sr = new StreamReader(path)){textData2 = (TextData)ser444.Deserialize(sr);}// 验证反序列化结果if (textData2 != null){print("反序列化成功!");print("文本: " + textData2.text);print("年龄: " + textData2.age);}}
}
3.5.6 IXmlSerializable接口的优势和应用场景

优势:

  1. 完全控制:可以完全控制XML的读写过程
  2. 灵活性:支持复杂的XML结构和自定义格式
  3. 性能优化:可以针对特定需求优化序列化性能
  4. 兼容性:可以处理不同版本的XML格式

应用场景:

  1. 复杂数据结构:当默认序列化无法处理复杂的数据结构时
  2. 自定义格式:需要生成特定格式的XML时
  3. 性能要求:对序列化性能有特殊要求时
  4. 版本兼容:需要处理不同版本的XML格式时
3.5.7 注意事项和最佳实践

1. 实现要求

// 必须实现所有三个方法
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader) { /* 自定义读取逻辑 */ }
public void WriteXml(XmlWriter writer) { /* 自定义写入逻辑 */ }

2. 错误处理

public void ReadXml(XmlReader reader)
{try{// 自定义读取逻辑reader.Read();text = reader.Value;}catch (System.Exception e){Debug.LogError("XML读取失败: " + e.Message);}
}

通过实现 IXmlSerializable 接口,可以为Unity项目提供高度自定义的XML序列化解决方案,特别适合需要精确控制XML格式的复杂应用场景。

http://www.dtcms.com/a/312420.html

相关文章:

  • java:判断两个实例(对象)相等
  • 多向量检索:lanchain,dashvector,milvus,vestorsearch,MUVERA
  • RabbitMQ面试精讲 Day 9:优先级队列与惰性队列
  • SQL154 插入记录(一)
  • 十八、Javaweb-day18-前端实战-登录
  • JavaScript 性能优化实战指南:从运行时到用户体验的全面提升​
  • 【openlayers框架学习】十:openlayers中控件的使用
  • 学习笔记《区块链技术与应用》第六天 问答 匿名技术 零知识证明
  • Apple基础(Xcode④-Flutter-Platform Channels)
  • Stream 过滤后修改元素,却意外修改原列表
  • Swift 运算符
  • 【Django】-9- 单元测试和集成测试(上)
  • Android 之 蓝牙通信(4.0 BLE)
  • Redis+Lua的分布式限流器
  • C++编译过程与GDB调试段错误和死锁问题
  • 北邮:LLM强化学习架构Graph-R1
  • C++-二叉树OJ题
  • 【反转字符串中的单词】
  • 从零开始设计一个分布式KV存储:基于Raft的协程化实现
  • 吴恩达【prompt提示词工程】学习笔记
  • C# async await 实现机制详解
  • GR-3:字节跳动推出40亿参数通用机器人大模型,精确操作提升250%,开启具身智能新纪元!
  • FasrCGI
  • ospf笔记和 综合实验册
  • visual studio code 怎样将主题修改成亮色,并且配置中文界面
  • zookeeper常见命令和常见应用
  • MySQL——运维篇
  • K8S部署ELK(五):集成Kibana实现日志可视化
  • MySQL面试题及详细答案 155道(021-040)
  • 使用Database Navigator插件进行连接sqlite报错invalid or incomplete database