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等环境)。
在前文:“实体类配合数据库表字段进行属性扩展” 一文中介绍了如何使用 DynamicObject 进行属性的扩展,但该类在MVC下进行JSON序列化时其序列化的结果并不友好。本文主要讨论的是如何友好地对 DynamicObject 继承类进行JSON序列化。
要对 DynamicObject 对象实现JSON的序列化,其实只需在 DynamicObject 的继承类中实现 IDictionary<string,object> 接口即可,因为 JavaScriptSerializer 和 Json.NET 均支持对 IDictionary<string,object> 的序列化,该接口主要对 DynamicObject 对象的属性和值进行管理。前文所述的ExtensionObject类就继承自DynamicObject类,并实现了 IDynamicMetaObjectProvider 和 IDictionary<string,object> 接口。
在MVC中原生态的 JavascrioptSerializer 序列化时会使用 IDictionary<string,object> 的实现方法 System.Collections.IEnumerable.GetEnumerator() 来获取要序列化的属性名。
而Json.NET则调用 IDictionary<string,object> 的实现方法 IEnumerable<KeyValuePair<string, object>>.GetEnumerator() 来获取属性及其值。
但二者最大的区别是,使用JavascrioptSerializer将序列化成如下的JSON格式:
{{"Key":"Code","Value":"4"},{"Key":"ID","Value":"d8ea26b06d9d4c7e85ccc43da71320ac"},{"Key":"LongName","Value":"null"}, {"Key":"FCode","Value":"/51/5100/4"},{"Key":"NodeLevel","Value":"3"}}
而使用Json.NET则序列化为:{"ID": "d8ea26b06d9d4c7e85ccc43da71320ac","Code": "4","LongName": null,"FCode": "/51/5100/4","NodeLevel": 3}
毫无疑问,使用Json.NET进行序列化更符合实际的情况和需要,而且速度还更快。当然,在WebApi下,因为已使用了Json.NET作为默认的序列化组件,并不存在上述问题,因此本文将主要对MVC中对DynamicObject的Json.NET序列化的实现进行说明。
一、MVC下使用Json.NET序列化
1、实现自定义ActionResult,继承自JsonResult类,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 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); } } } } |
2、对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 }; } } }
3、调用方式的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); } }
二、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
下一章将分享WebApi和MVC下的提升性能的一些经验。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee
· 用 DeepSeek 给对象做个网站,她一定感动坏了
· .NET 8.0 + Linux 香橙派,实现高效的 IoT 数据采集与控制解决方案
· .NET中 泛型 + 依赖注入 的实现与应用