之前寫過一篇 如何用 C# 撰寫序列化(Serialize)與反序列化(Deserialize),最近正好又有專案用上,心想乾脆寫一個泛型的版本,讓以後所有專案都可以使用。
完整的程式碼如下:
using System.IO;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
public static class SiteHelper
{
public static string Serialize(object o)
{
XmlSerializer ser = new XmlSerializer(o.GetType());
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb);
ser.Serialize(writer, o);
return sb.ToString();
}
public static T Deserialize<T>(string s)
{
XmlDocument xdoc = new XmlDocument();
try
{
xdoc.LoadXml(s);
XmlNodeReader reader = new XmlNodeReader(xdoc.DocumentElement);
XmlSerializer ser = new XmlSerializer(typeof(T));
object obj = ser.Deserialize(reader);
return (T)obj;
}
catch
{
return default(T);
}
}
}
序列化(Serialize) 與 反序列化(Deserialize) 時的用法如下:
TestClass myObject = new TestClass { ID = "test"; };
// 將 myObject 物件序列化成 Xml 格式 (字串型態)
string s = SiteHelper.Serialize(myObject);
// 將 s 字串反序列化成 TestClass 型別的物件
TestClass o = SiteHelper.Deserialize<TestClass>(s);
---
在序列化的過程中其實並非所有物件都可以序列化,只要序列化失敗就會引發 Exception,但我的程式在寫「反序列化」已經做了 try/catch,所以只要反序列化失敗會直接回傳該型別的預設值 ( 只要是參考型別就會回傳 null ),在這裡我利用 C# 中的 default 關鍵字來取得應用泛型時物件的預設值。
像我在測試的過程中發現 System.Net.IPAddress 或 System.Net.NetworkInformation.PhysicalAddress 這些型別都會無法進行序列化,錯誤訊息如下:
System.Net.NetworkInformation.PhysicalAddress cannot be serialized because it does not have a parameterless constructor.
解決的方法有兩種:
- 修改類別屬性,改用 string 型別儲存資料。
- 繼承無法序列化的型別,並實做 ISerializable 介面自訂序列化方法。
相關連結