Xml序列化
Xml文件格式是一种非常有用的格式,在跨平台方面做的异常出色。实际中常使用Xml文件作为配置文件或者是数据的存贮文件。采用Xml文件绝对比简单的txt或者ini文件更有效,也绝对比采用注册表格让人喜欢。
单个对象的序列化需要实现[Serializable]特性。需要一个无参的构造函数,并且不对外部无法访问的数据进行操作,比如私有的数据成员。通常不提倡将本应私有的数据成员(字段)设置为公有,这样做破坏了数据的封装性,带来潜在的安全隐患。一般要给需要的序列化的成员实现公有的get和set属性,这样数据可从外部安全的访问,也可正常的进行序列化。
实际中通常还使用的是ArrayList对象的序列化。这样可以在一次的序列化过程中处理很多的工作,而且在反序列化后不失对象之间的结构关系。
下面我们开始演练Xml格式的序列化。
这里的测试对象如下所示:
/// <summary>
/// 要进行序列化的测试类
/// </summary>
[Serializable]
public class Test
{
private string m_ID;
private string m_Name;
public string ID
{
get{return m_ID;}
set{m_ID = value;}
}
public string Name
{
get{return m_Name;}
set{m_Name = value;}
}
public override string ToString()
{
return m_ID + "\t" + m_Name;
}
public Test()
: this("", "")
{
}
public Test(string id, string name)
{
m_ID = id;
m_Name = name;
}
public void Show()
{
Console.WriteLine(this.ToString());
}
}
添加了XmlSerializeTools实用工具类来辅助进行Xml的操作:
using System;
using System.Collections;
using System.Xml;
using System.Xml.Serialization;
namespace ymz
{
/// <summary>
/// Xml序列化和反序列化的实用工具
/// </summary>
public class XmlSerializeTools
{
/// <summary>
/// 执行单个对象的序列化
/// </summary>
/// <param name="fileName">序列化的目标文件路径名</param>
/// <param name="data">要序列化的对象</param>
/// <param name="type">要序列化的对象类型(可以通过typeof(*)的格式获取)</param>
public static void XmlSerializeObject(string fileName,object data, Type type)
{
XmlTextWriter xtw = new XmlTextWriter(fileName, System.Text.Encoding.UTF8);
XmlSerializer xs = new XmlSerializer(type);
xs.Serialize(xtw, data);
xtw.Close();
}
/// <summary>
/// 执行单个对象的反序列化
/// </summary>
/// <param name="fileName">反序列化的原文件路径名</param>
/// <param name="type">要反序列化的对象类型(可以通过typeof(*)的格式获取)</param>
/// <returns>反序列化后的对象</returns>
public static Object XmlDeserializeObject(string fileName, Type type)
{
XmlSerializer xolds = new XmlSerializer(type);
XmlTextReader xt = new XmlTextReader(fileName);
object data = xolds.Deserialize(xt);
xt.Close();
return data;
}
/// <summary>
/// ArrayList的序列化
/// </summary>
/// <param name="fileName">序列化的目标文件路径名</param>
/// <param name="arrayList">要序列化的ArrayList对象</param>
public static void XmlSerializeArrayList(string fileName, ArrayList arrayList)
{
XmlSerializer xs = new XmlSerializer(typeof(ArrayList));
__XmlSerializeArrayList(fileName, arrayList, xs);
}
/// <summary>
/// ArrayList的序列化
/// </summary>
/// <param name="fileName">序列化的目标文件路径名</param>
/// <param name="arrayList">要序列化的ArrayList对象</param>
/// <param name="extraTypes">ArrayList中对象类型信息
/// (当ArrayList中为复杂类型时需提供该参数。可以通过"new Type[]{*, *}"格式提供)</param>
public static void XmlSerializeArrayList(string fileName, ArrayList arrayList,
Type[] extraTypes)
{
XmlSerializer xs = new XmlSerializer(typeof(ArrayList), extraTypes);
__XmlSerializeArrayList(fileName, arrayList, xs);
}
private static void __XmlSerializeArrayList(string fileName, ArrayList arrayList
, XmlSerializer xs)
{
XmlTextWriter xtw = new XmlTextWriter(fileName, System.Text.Encoding.UTF8);
xs.Serialize(xtw, arrayList);
xtw.Close();
}
/// <summary>
/// ArrayList的反序列化
/// </summary>
/// <param name="fileName">反序列化的原文件路径名</param>
/// <returns>反序列化后的ArrayList对象</returns>
public static ArrayList XmlDeserializeArrayList(string fileName)
{
XmlSerializer xolds = new XmlSerializer(typeof(ArrayList));
return __XmlDeserializeArrayList(fileName, xolds);
}
/// <summary>
/// ArrayList的反序列化
/// </summary>
/// <param name="fileName">反序列化的原文件路径名</param>
/// <param name="extraTypes">ArrayList中对象类型信息
/// (当ArrayList中为复杂类型时需提供该参数。可以通过"new Type[]{*, *}"格式提供)</param>
/// <returns>反序列化后的ArrayList对象</returns>
public static ArrayList XmlDeserializeArrayList(string fileName, Type[] extraTypes)
{
XmlSerializer xolds = new XmlSerializer(typeof(ArrayList), extraTypes);
return __XmlDeserializeArrayList(fileName, xolds);
}
private static ArrayList __XmlDeserializeArrayList(string fileName, XmlSerializer xolds)
{
XmlTextReader xt = new XmlTextReader(fileName);
ArrayList list = (ArrayList)xolds.Deserialize(xt);
xt.Close();
return list;
}
}
}
简单类型的ArrayList比如ArrayList<int>之类的,可以直接调用函数XmlSerializeArrayList和XmlDeserializeArrayList函数的二参数版本处理,系统会自动默认的提供相应的类型信息。但是如果要实现复杂类型,比如自定义的结构体或者类时,需要明确的指出对象的类型信息。这时需要采用XmlSerializeArrayList和XmlDeserializeArrayList函数的三参数版本。
下面是我的测试函数:
static void Main(string[] args)
{
string pathBase = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\";
Test t1 = new Test("dearymz@163.com", "秒大刀");
t1.Show();
ymz.XmlSerializeTools.XmlSerializeObject(pathBase + "object.xml", t1, typeof(Test));
Test t2 = (Test)ymz.XmlSerializeTools.XmlDeserializeObject(pathBase + "object.xml", typeof(Test));
t2.Show();
ArrayList a1 = new ArrayList();
a1.Add(t1);
a1.Add(t2);
foreach(Test t in a1)
{
t.Show();
}
ymz.XmlSerializeTools.XmlSerializeArrayList(pathBase + "ArrayList.xml", a1, new Type[]{typeof(Test)});
//下面方法抛出“未处理的异常: System.InvalidOperationException: 生成 XML 文档时出错。”异常
//ymz.XmlSerializeTools.XmlSerializeArrayList(pathBase + "ArrayList.xml", a1);
ArrayList a2 = ymz.XmlSerializeTools.XmlDeserializeArrayList(pathBase + "ArrayList.xml", new Type[]{typeof(Test)});
//下面方法抛出“未处理的异常: System.InvalidCastException: 指定的转换无效。”异常
//ArrayList a2 = ymz.XmlSerializeTools.XmlDeserializeArrayList(pathBase + "ArrayList.xml");
foreach(Test t in a2)
{
t.Show();
}
}
结论:
对于复杂类型集合的序列化操作时一定要明确指出其类型信息。
(由于页面空间的限制,这里略去了所有的代码格式和颜色信息)
评论