2020年12月19日 星期六

Deserialize注意事項 - 動態型別(Dynamic)屬性為物件時

程式開發一段時間,對於序列化各個眉角,沒碰過一萬應該也有一千(誤),累積了不少經驗;

應該大部分情境也都能分出注意事項,逢凶化吉~,但這次dynamic 情境算是上了一課,

凡事還是小心為妙,別一昧的依賴經驗。在開始說明前先對於 dynamic 整理一點點資訊。


dynamic 型別在.net 4.0 出現,畢竟在靜態程式語言出現動態型別,在當時造成熱烈討論,網路

上各路大神也都有不少討論,這邊也就順手列一下資源,也算是方便自己查閱。




其中,因dynamic 的特行為執行時期決定型別的特性,在有需要實作Reflection 時可以減少一點

程式碼,並且不影響閱讀障礙,這個在開發COM 時,會帶來不錯的效益收入。但若設計在Class

的Property 那就需要注意一下下了,以下設計模擬情境。


假設我們需要設計統一的API 回傳格式,大概如下,其中 Status 代表成功或失敗,ErrMsg 代表

若錯誤訊息,Result 為回傳的內容。


程式設計如下,其中 Result 屬性設計為dynamic 型別

因為設計為dynamic 型別,我想應該就是希望未來Result 屬性可以吃任何的類別,達到一開始

設定的格式一致的效果,觀看序列話後的結果也滿合理的;但關鍵點就是在使用者接收到回傳

回來的資料,在後續應用中會不小心掉入小洞,會有一點點痛。


當使用者收到json內容後,可能都是直接反序列化應用,如下。



我們期待反序列化後,取得response 物件並針對Result 屬性轉型別為 Person,後續取得Name 

屬性印出值,但出現了錯誤。錯誤訊息說明這個person 變數為null ,表示在 as Person 時應該

沒有成功,所以,我們回頭檢視一下 response.Result 屬性的值是甚麼?


由上圖可知,它其實還是一個 json 內容,咦~怎麼不是自動為Person 內容,但想想也是啦,因為

dynamic 的特性為執行時期才決定型別,而遇到反序列化時,當然不知道要以哪個物件為基底

來轉型,故在 as type 時就會得到null 值,那該可以怎麼處理這個狀況呢?


第一個,既然知道Result 內容為json ,那就再反序列化為person 即可


第二個,可以透過Json.net  的JObject 、JProperty 技法



回到API 回應格式設計,覺得還是會將屬性設計為 object 型別,避免同性質專案,client 端使用

時想太多,限制範圍為資料操作,不做額外操作。


後續思考dynamic 使用情境,大概以下面為主,其他暫不考慮

  • 若有動態擴展屬性或方法需求時

  • 大量使用反射設計時減少程式量

沒有留言:

張貼留言