YbSoftwareFactory 代碼生成插件【二十】:DynamicObject的序列化

    DynamicObject 是 .NET 4.0以來才支持的一個類,但該類在.NET 4.0下未被標記爲[Serializable] Attribute,而在.NET 4.5下則被標記了[Serializable] Attribute。須要注意的是,若是你使用須要進行XML序列化等操做(例如WCF中),部署到未安裝.NET 4.5的環境中一般會報錯並提示異常,而無論你編譯時使用的目標平臺是.NET 4.0 仍是 .NET 4.5。一般這個錯誤在安裝了.NET 4.5環境的開發機上一般沒有問題,即便你建立的項目是基於.NET 4.0的,但實際調用的仍是 .NET 4.5的庫。所以一般在使用 DynamicObject 並須要進行序列化的情景下須要謹慎(特別是WCF環境下),除非你實現了你自定義的序列化操做。在此提醒廣大開發人員注意,不然到你正式部署至不能安裝.NET 4.5的環境中將折騰你夠嗆(例如Windows Server 2003等環境)。html

    在前文:「實體類配合數據庫表字段進行屬性擴展」 一文中介紹瞭如何使用 DynamicObject 進行屬性的擴展,但該類在MVC下進行JSON序列化時其序列化的結果並不友好。本文主要討論的是如何友好地對 DynamicObject 繼承類進行JSON序列化。數據庫

    要對 DynamicObject 對象實現JSON的序列化,其實只需在 DynamicObject 的繼承類中實現 IDictionary<string,object> 接口便可,由於 JavaScriptSerializer 和 Json.NET 均支持對 IDictionary<string,object> 的序列化,該接口主要對 DynamicObject 對象的屬性和值進行管理。前文所述的ExtensionObject類就繼承自DynamicObject類,並實現了 IDynamicMetaObjectProvider 和 IDictionary<string,object> 接口。json

    在MVC中原生態的 JavascrioptSerializer 序列化時會使用 IDictionary<string,object> 的實現方法 System.Collections.IEnumerable.GetEnumerator() 來獲取要序列化的屬性名。api

    而Json.NET則調用 IDictionary<string,object> 的實現方法 IEnumerable<KeyValuePair<string, object>>.GetEnumerator() 來獲取屬性及其值。app

    但兩者最大的區別是,使用JavascrioptSerializer將序列化成以下的JSON格式:框架

{{"Key":"Code","Value":"4"},{"Key":"ID","Value":"d8ea26b06d9d4c7e85ccc43da71320ac"},{"Key":"LongName","Value":"null"},           {"Key":"FCode","Value":"/51/5100/4"},{"Key":"NodeLevel","Value":"3"}}ide

    而使用Json.NET則序列化爲:{"ID": "d8ea26b06d9d4c7e85ccc43da71320ac","Code": "4","LongName": null,"FCode": "/51/5100/4","NodeLevel": 3}oop

    毫無疑問,使用Json.NET進行序列化更符合實際的狀況和須要,並且速度還更快。固然,在WebApi下,由於已使用了Json.NET做爲默認的序列化組件,並不存在上述問題,所以本文將主要對MVC中對DynamicObject的Json.NET序列化的實現進行說明。性能

    1、MVC下使用Json.NET序列化ui

    一、實現自定義ActionResult,繼承自JsonResult類,代碼以下:

using System;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace YbRapidSolution.Presenter.JsonNet
{
    public class JsonNetResult : JsonResult
    {
        public JsonSerializerSettings SerializerSettings { get; set; }
        public JsonNetResult()
            : base()
        {
            // create serializer settings
            this.SerializerSettings = new JsonSerializerSettings();
            // 阻止屬性循環引用的狀況下出現的異常
            this.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            // setup default serializer settings
            this.SerializerSettings.Converters.Add(new IsoDateTimeConverter());
        }
        public JsonNetResult(string contentType)
            : this()
        {
            ContentType = contentType;
        }
        public JsonNetResult(string contentType, System.Text.Encoding contentEncoding)
            : this(contentType)
        {
            ContentEncoding = contentEncoding;
        }
        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");
            if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
                String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
            {
                throw new InvalidOperationException("Json request GET not allowed");
            }
            // 獲取當前 http context response
            var response = context.HttpContext.Response;
            // 設置 content type
            response.ContentType = !String.IsNullOrEmpty(ContentType) ? ContentType : "application/json";
            // 設置 encoding
            if (ContentEncoding != null)
                response.ContentEncoding = this.ContentEncoding;
            if (Data != null)
            {
                // 使用 JSON.Net 把對象序列化爲 JSON 
                string jsonText = JsonConvert.SerializeObject(this.Data, Formatting.Indented, this.SerializerSettings);
                // write the response
                response.Write(jsonText);
            }
        }
    }
}

    二、對Controller進行方法的擴展

using System.Dynamic;
using System.Web.Mvc;
using YbRapidSolution.Presenter.Controllers;

namespace YbRapidSolution.Presenter.JsonNet
{
    public static class JsonNetControllerExtensions
    {
        public static JsonNetResult JsonNet(this Controller controller, object data)
        {
            return new JsonNetResult() { Data = data };
        }
        public static JsonNetResult JsonNet(this Controller controller, object data,string contentType)
        {
            return new JsonNetResult(contentType) { Data = data };
        }
    }
}

    三、調用方式的Demo以下:

/// <summary>
        /// 查找當前登陸用戶的當前崗位對本模塊所具備的動做權限集合
        /// </summary>
        /// <param name="orgFId">當前登陸用戶所使用的崗位(人員成員)的標識全路徑</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        [YbMvcAuthorize(PermissionKeys = PERMISSIONKEY)]
        public JsonResult FindAllowActionsFor(string orgFId)
        {
            try
            {
                var curMessage = new EasyUIMessage(true, "權限項加載成功");
                //查詢類型爲按鈕或右鍵菜單的動做
                var actions = _permissionService
                    .FindControlsForOrgByKeyAndOrgFId(PERMISSIONKEY,orgFId);
                
                curMessage.data = actions;
                return this.JsonNet(curMessage);
            }
            catch (Exception er)
            {
                var curMessage = new EasyUIMessage(false, string.Format("權限項加載失敗:{0}", er.Message));
                return this.JsonNet(curMessage);
            }
        }

    2、Web Api下使用Json.NET序列化

    Web Api由於使用Json.NET做爲默認的JSON序列化實現框架,一般需在 WebApiConfig 類的 Register 中寫以下的代碼進行配置便可:

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling
                = ReferenceLoopHandling.Serialize;
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling
                = PreserveReferencesHandling.Objects; 

    如需瞭解更多請點擊:權限模型+流程專家 Demo

    附一:ExtensionObject源碼

    附二:YbSoftwareFactory操做手冊

    附三:YbSoftwareFactory底層組件幫助文檔

    下一章將分享WebApi和MVC下的提高性能的一些經驗。

相關文章
相關標籤/搜索