在 C# 開發中,資料持久化是常見需求。XML 序列化提供了一種將物件轉換為 XML 格式並能還原的機制,廣泛應用於設定檔儲存、Web Service 通訊等場景。本文將透過完整範例示範如何使用 XmlSerializer 進行物件的序列化與反序列化操作。
首先建立 Person 與 Course 類別,並標記 [Serializable] 屬性:
[Serializable]
public class Person
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public string Sex;
public int Age = 31;
public Course[] Courses;
public Person() { }
public Person(string Name)
{
name = Name;
Sex = "男";
}
}
[Serializable]
public class Course
{
public string Name;
[XmlIgnore]
public string Description;
public Course() { }
public Course(string name, string description)
{
Name = name;
Description = description;
}
}
關鍵點說明:
[Serializable]:標記類別可被序列化[XmlIgnore]:標記 Description 欄位不參與 XML 序列化class Test
{
// 序列化:將物件寫入 XML 檔案
public void Serialize()
{
Person c = new Person("cyj");
c.Courses = new Course[2];
c.Courses[0] = new Course("英語", "交流工具");
c.Courses[1] = new Course("數學", "自然科學");
XmlSerializer xs = new XmlSerializer(typeof(Person));
using (Stream stream = new FileStream(@"c:\cyj.xml", FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
xs.Serialize(stream, c);
}
}
// 反序列化:從 XML 檔案還原物件
public void Deserialize()
{
XmlSerializer xs = new XmlSerializer(typeof(Person));
using (Stream stream = new FileStream(@"c:\cyj.xml", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
Person p = (Person)xs.Deserialize(stream);
Console.WriteLine(p.Name);
Console.WriteLine(p.Age);
Console.WriteLine(p.Courses.Length);
Console.Read();
}
}
}
最佳實踐: 使用 using 區塊自動管理資源釋放,避免檔案鎖定問題。
格式化後的 XML 輸出如下:
<?xml version="1.0"?>
<Person xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<Sex>男</Sex>
<Age>31</Age>
<Courses>
<Course>
<Name>英語</Name>
</Course>
<Course>
<Name>數學</Name>
</Course>
</Courses>
<Name>cyj</Name>
</Person>
觀察重點:
Name 為屬性,Sex、Age 為欄位)[XmlIgnore] 的 Description 不會出現在 XML 中使用 [XmlElement("自訂名稱")] 或 [XmlAttribute] 控制輸出格式:
[XmlElement("PersonName")]
public string Name { get; set; }
[XmlAttribute("Gender")]
public string Sex;
透過 XmlSerializerNamespaces 移除預設命名空間:
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
xs.Serialize(stream, c, ns);
使用 [XmlInclude(typeof(具體類別))] 指定衍生類型:
[XmlInclude(typeof(Course))]
public abstract class BaseCourse { }
| 問題 | 原因 | 解決方法 |
|---|---|---|
| InvalidOperationException | 缺少預設建構函式 | 確保類別有無參數建構函式 |
| 循環參考錯誤 | 物件圖包含循環引用 | 使用 [XmlIgnore] 或資料傳輸物件 (DTO) |
| 型別無法序列化 | 介面、Dictionary 等不支援直接序列化 | 轉換為陣列或 List,或實作 IXmlSerializable |
| 編碼問題 | 預設 UTF-8 可能不符需求 | 使用 XmlWriter 指定 Encoding |
XmlSerializer 首次建構時會動態產生組件,有啟動成本DataContractSerializer 或二進位序列化XmlSerializer 實例可避免重複產生組件XML 序列化是 C# 處理資料持久化的基礎技能。掌握 XmlSerializer 的核心用法、屬性控制、例外處理與效能優化,能讓你在設定檔管理、API 整合、資料匯出等場景中遊刃有餘。建議實務上搭配單元測試驗證序列化還原邏輯,確保資料完整性。