C# [Serializable]

  • 547
  • 0

遇到過幾次使用 [Serializable] 相關的問題,整理一下。

為什麼需要序列化?http://stackoverflow.com/a/5877839/4963421

最早用到序列化是要做 deep clone:複製一個相同的 object,避免改值的時候因為 by reference意外改到原本的資料;做法大概像這樣:http://stackoverflow.com/a/78612/4963421
但那時候 class的定義很多層,要找到每一個 class加上 [Serializable]其實有點囉唆,
後來試過用 Reflection逐個 property複製,感覺不快,也真的不快,還要自己寫…
最後是用 json.net把 object轉成 json字串再反解回來。

接著是 session,開發的時候 web.config設定是 <sessionState mode="InProc" />,上線後 session常常不見,於是改成 mode="StateServer";改完之後發現 session如果有存物件而該 class又沒宣告 [Serializable]就會噴錯,沒什麼好方法,只能一個一個加,有些用到 entity framework產生的 class,於是就用 partial class把這些宣告放在同個檔案,看起來整齊一點。

再繼續測發現原本正常的 web api回傳的 json字串壞掉了,不知從哪跑出 k__BackingField欄位,google發現原因是 class定義加了 [Serializable],http://stackoverflow.com/a/946088/4963421提出的解法是不要用 [Serializable],改用 [DataContract]、[DataMember]…光想就累了,完全不想試;後來看到可以在 WebApiConfig設定忽略 [Serializable]

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API 設定和服務

        // Web API 路由
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            //routeTemplate: "api/{controller}/{id}",
            defaults: new { action = RouteParameter.Optional, id = RouteParameter.Optional }
            //defaults: new { id = RouteParameter.Optional }
        );

        // 預設回傳 json格式
        var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
        config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);

        // 忽略 [Serializable]
        config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
            new Newtonsoft.Json.Serialization.DefaultContractResolver
            {
                IgnoreSerializableAttribute = true
            };
        // 遇到時間欄位預設轉成 utc
        config.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
    }
}

沒再發現問題,(暫時 QQ)打完收工。