一、Ixmllserializable是什么?
是C#中的XmlSerializer中提供了可拓展内容
可以让一些无法被序列化和反序列化的特殊类能被序列化(如Dictionary)
让特殊类继承Ixmllserializable接口,实现其中的方法即可
二、自定义类实践
实践前须知:
将演示对这个数据结构类进行序列化和反序列化
public class PlayerInfo
{
public int lv; //等级
public string name; //名字
}
直接上代码:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using UnityEngine;
//准备一个自定义类,用来被序列化
// 继承IXmlSerializable接口,继承此接口后,将会使用我们自定义的序列化规则
public class PlayerInfo : IXmlSerializable
{
public int lv;
public string name;
//实现继承IXmlSerializable接口中的三个方法
/// <summary>
/// 方法1
/// </summary>
/// <returns></returns>
public XmlSchema GetSchema()
{
//直接返回空即可
return null;
}
/// <summary>
///方法2:该类被序列化时,会自动调用
/// 自定义我们自己的序列化规则
/// </summary>
/// <param name="writer">根节点</param>
public void WriteXml(XmlWriter writer)
{
//reader代表的就是根节点(PlayerInfo)
//如果要自定义序列化规则,一定会用到XmlWriter中的方法来进行序列化
//1.写节点
writer.WriteElementString("lv", this.lv.ToString());
writer.WriteElementString("name", this.name.ToString());
//2.写节点的子节点
// WriteStartElement和WriteEndElement一定是配对出现的
XmlSerializer s = new XmlSerializer(typeof(int));
writer.WriteStartElement("lv");
s.Serialize(writer, lv);
writer.WriteEndElement();
XmlSerializer s2 = new XmlSerializer(typeof(string));
writer.WriteStartElement("name");
s2.Serialize(writer, name);
writer.WriteEndElement();
//3.写属性
// 参数1 属性名
// 参数2 属性的值
//writer.WriteAttributeString("lv", this.lv.ToString());
//writer.WriteAttributeString("name", "义眼鼎针");
}
/// <summary>
///方法3:该类被反序列化时,会自动调用
/// 自定义我们自己的反序列化规则
/// </summary>
/// <param name="reader"></param>
public void ReadXml(XmlReader reader)
{
//reader代表的就是根节点(PlayerInfo)
//1.读节点
// 读节点方法一:一块一块读
// 读节点的形式有些奇葩,是一块一块往下读
// 可用以下代码对比xml文件中的节点来理解
reader.Read();//这是读到了<lv>节点
reader.Read();//这是读到了<lv>节点包裹的内容
this.lv = int.Parse(reader.Value);//这是读到<lv>节点的包裹内容的值(12)
reader.Read();//这是读到了</lv>
reader.Read();//这是读到了<name>节点
reader.Read();//这是读到了<name>节点包裹的内容
this.name = reader.Value;//这是读到<name>节点的包裹内容的值(义眼鼎针)
// 读节点方法二:循环配合类型判断
while (reader.Read())
{
// 如果类型是Element(节点)
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
// PlayerInfo中有两个节点
case "lv":
reader.Read();
this.lv = int.Parse(reader.Value);
break;
case "name":
reader.Read();
this.name = reader.Value;
break;
}
}
}
//2.读节点的子节点
XmlSerializer s = new XmlSerializer(typeof(int));
XmlSerializer s2 = new XmlSerializer(typeof(string));
// 跳过根节点
reader.Read();
reader.ReadStartElement("lv");
this.lv = (int)s.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("name");
this.name = s2.Deserialize(reader).ToString();
reader.ReadEndElement();
//3.读属性
//this.lv = int.Parse(reader["lv"]);
//this.name = reader["name"];
}
}
public class Lesson3 : MonoBehaviour
{
void Start()
{
PlayerInfo p = new PlayerInfo();
p.lv = 12;
p.name = "义眼鼎针";
string path = Application.persistentDataPath + "/PlayerInfo.xml";
//对这个对象将进行序列化
using (StreamWriter writer = new StreamWriter(path))
{
//声明序列化“翻译器”
XmlSerializer s = new XmlSerializer(typeof(PlayerInfo));
//传入要写到哪里 和 写谁
s.Serialize(writer, p);
}
//对这个对象将进行反序列化
using (StreamReader reader = new StreamReader(path))
{
//声明反序列化“翻译器”
XmlSerializer s = new XmlSerializer(typeof(PlayerInfo));
PlayerInfo p2 = s.Deserialize(reader) as PlayerInfo;
}
}
}