通用 XML 序列化方法






4.11/5 (7投票s)
一个 XML 助手类,
介绍
我一直在寻找 XML 包装器来序列化和反序列化我的对象,但毫无结果。 显然,互联网上很少有能做到这一点的东西,除非你想使用像Karvonite 这样的完整对象状态管理解决方案,但与任何外部解决方案一样,它也会带来开销、错误等等。
我所寻找的是直观的简单,一种我可以重用的 XML Save | Load 方法,适用于任何对象类型。 来自 Devhood 的 Andrew Ma 撰写了一篇文章,解决了特定对象类型的问题。
但是,它没有考虑到以下几点
- 能够根据对象的类型自动命名 XML 文件。 这避免了程序员必须将他的 XML 文件名映射到他试图序列化的对象。
- 能够将任何对象传递给 XML 方法进行序列化和反序列化,而无需担心其类型(当然,前提是该对象是可序列化的,如果所有要序列化的字段都标有适当的
XMLAttribute
,例如类变量名为“password
”的[XmlAttribute("Password")]
。 请参阅图 1。)图 1:正确序列化的类(带有 XmlAttribute) - 保持
XmlSerializer
的状态(命名空间:System.Xml.Serialization
),而无需为 Serialize 或 De-Serialize 方法重新初始化它。
为了实现上述目标,我利用 C# 的一个特性,称为泛型,以提供类型独立性,以便在任何 C# 应用程序中为任何可序列化对象利用我的 XML 帮助器类。
背景
使用方法
要运行代码,您需要 Visual Studio 2008 Express。 所有相应的导入和引用都已完成。
测试类(将被序列化为 XML)
我用来测试的 main
类文件称为 UserList
,它主要包含一个 System.Collection.ArrayList
的 User
类,而 User
类又包含一堆原始 C# 数据类型。
这是一个很好的例子,可以测试可以说是复杂数据结构/类的自动序列化。
// UserList.cs
using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace TESTXML
{
// Shopping list class which will be serialized
[XmlRoot("UserList")]
public class UserList
{
private ArrayList myUserList;
public UserList()
{
myUserList = new ArrayList();
}
[XmlElement("myUsers")]
public User[] myUsers
{
get
{
User[] myUsers = new User[myUserList.Count];
myUserList.CopyTo(myUsers);
return myUsers;
}
set
{
if (value == null)
return;
User[] myUsers = (User[])value;
myUserList.Clear();
foreach (User myUser in myUsers)
myUserList.Add(myUser);
}
}
public string AddItem(User myUser)
{
myUserList.Add(myUser);
return myUser.ToString();
}
}
}
测试子类(也将自动序列化为 XML)
//User.cs
public class User
{
[XmlAttribute("UserName")]
public String UserName = "";
[XmlAttribute("Email")]
public String Email = "";
[XmlAttribute("Password")]
public String Password = "";
[XmlAttribute("TotalScore")]
public int TotalScore = 0;
[XmlAttribute("IsApproved")]
public Boolean IsApproved = false;
public User(string myUserName, String myEmail, String myPassword,
int myTotalScore, Boolean myIsApproved)
{
UserName = myUserName;
Email = myEmail;
Password = myPassword;
TotalScore = myTotalScore;
IsApproved = myIsApproved;
}
public override string ToString()
{
return "UserName: " + UserName + ", Email: " + Email + ",
TotalScore = " + TotalScore + ", IsApproved = " + IsApproved;
}
}
主要的 XML 帮助器类,可以将传递给它的任何类的任何可序列化对象进行序列化/反序列化
//Main File: XMLHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Collections;
namespace TESTXML
{
public class XMLHelper <T>
{
XmlSerializer mySerializer ;
String ClassName;
String BaseDirectory;
public XMLHelper()
{
mySerializer = new XmlSerializer(typeof(T));
BaseDirectory = "";
}
public XMLHelper(String myBaseDirectory)
{
mySerializer = new XmlSerializer(typeof(T));
BaseDirectory = myBaseDirectory;
}
public String FileName(T myObj)
{
ClassName = myObj.GetType().Name;
return BaseDirectory + @"\" + ClassName + ".xml";
}
public void Save(T myObj)
{
TextWriter myWriter = new StreamWriter(FileName(myObj));
mySerializer.Serialize(myWriter, myObj);
myWriter.Close();
}
public T Load(T myObj)
{
XmlSerializer mySerializer = new XmlSerializer(typeof(T));
TextReader myReader = new StreamReader(FileName(myObj));
T NewObject = (T)mySerializer.Deserialize(myReader);
myReader.Close();
return NewObject;
}
}
}
关注点
public String FileName(T myObj)
{
ClassName = myObj.GetType().Name;
return BaseDirectory + "\\" + ClassName + ".xml";
}
请注意在上面,我是如何使用 GetType
方法提取对象文件名的,以及一个概念性的反射概念,以便为相应的对象在相应的基本目录中自动生成一个 ***.xml 文件名。
这增加了一级可重用性,同时减少了程序员需要注意的一件事,即用于将磁盘上的 XML 文件名映射到用户对象的命名约定。 一个漂亮的小调整。
Using the Code
将 BaseDirectory
初始化为相对于项目默认输出目录的 XML 文件路径位置。
使用要调用的对象的类型实例化一个新的 XMLHelper
类,在本例中仅为类名。
稍后在任何时候,从 XMLHelper
类重新加载相同的对象。 (注意:XMLHelper
类可以重新实例化,您只需要基本目录,最终应该将其设置为项目设置。)
UserList myListOfUsers = new UserList();
String BaseDirectory = "Data/XML"
XMLHelper<UserList>myXMLHelper = new XMLHelper<UserList>(BaseDirectory);
myListOfUsers = null;
//Load From BaseDirectory
myListOfUsers = (UserList)myXMLHelper.Load(myListOfUsers);
结果
创建/加载测试对象使用两个 User
初始化 UserList
序列化对象将刚刚创建的 UserList
对象序列化为 XML 并将其写入磁盘,同时重置该对象。
反序列化对象获取对象的 FilePath
(通过简单地接受作为参数的 Object
类型,如上面 FileName
函数中所示),从磁盘读取到内存,从而重新填充 UserList
类的对象。
过程完成。
您可以从本文顶部的链接下载附带的源代码和所有文件。