﻿# 用 C# 撰寫序列化(Serialize)與反序列化(Deserialize) - Part 2

之前寫過一篇 [如何用 C# 撰寫序列化(Serialize)與反序列化(Deserialize)](/post/2008/03/19/How-to-serialize-and-deserialize-using-C-NET)，最近正好又有專案用上，心想乾脆寫一個泛型的版本，讓以後所有專案都可以使用。

完整的程式碼如下：

```csharp
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) 時的用法如下：

```csharp
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](http://msdn.microsoft.com/zh-tw/library/xwth0h0d\(VS.80\).aspx) 關鍵字來取得應用泛型時物件的預設值。

像我在測試的過程中發現 [System.Net.IPAddress](http://msdn.microsoft.com/zh-tw/library/system.net.ipaddress.aspx) 或 [System.Net.NetworkInformation.PhysicalAddress](http://msdn.microsoft.com/zh-tw/library/system.net.networkinformation.physicaladdress\(VS.80\).aspx) 這些型別都會無法進行序列化，錯誤訊息如下：

> System.Net.NetworkInformation.PhysicalAddress cannot be serialized because it does not have a parameterless constructor.

解決的方法有兩種：

1.  修改類別屬性，改用 string 型別儲存資料。
2.  繼承無法序列化的型別，並實做 [ISerializable 介面](http://msdn2.microsoft.com/zh-tw/library/system.runtime.serialization.iserializable.aspx)自訂序列化方法。

**相關連結**

-   [Introducing XML Serialization](http://msdn.microsoft.com/en-us/library/182eeyhh\(VS.71\).aspx)
-   [Introducing Serialization in .NET](http://www.codeproject.com/KB/cs/NetSerialization.aspx)
-   [Examples of XML Serialization](http://msdn.microsoft.com/en-us/library/58a18dwa\(VS.71\).aspx)
-   [Troubleshooting Common Problems with the XmlSerializer](http://msdn.microsoft.com/en-us/library/aa302290.aspx)
-   [PRB: XML Serialization: System.Xml.XmlSerializer Does Not Serialize Default Values](https://web.archive.org/web/20130619053541/http://support.microsoft.com/kb/325691/en-us)
-   [XmlSerializer 類別](http://msdn.microsoft.com/zh-tw/library/system.xml.serialization.xmlserializer.aspx)
-   [ISerializable 介面](http://msdn2.microsoft.com/zh-tw/library/system.runtime.serialization.iserializable.aspx)
-   [泛型程式碼中的預設關鍵字 (C# 程式設計手冊)](http://msdn.microsoft.com/zh-tw/library/xwth0h0d\(VS.80\).aspx)
