上篇文章"理解C# 4 dynamic(2) – ExpandoObject的使用" 了解了ExpandoObject的基本使用。

但ExpandoObject的问题就是它是一个万金油,什么都可以做,但是又都不专注。

使用DynamicObject正好可以解决这个问题。这篇文章介绍DynamicJson是如何继承DynamicObject,包装一个用来处理Json的动态类型。

阅读目录:

一、JS可以灵活处理Json字符串

二、DynamicObject分析

三、DynamicJson代码

四、总结

一,JS可以灵活处理Json字符串

看下面的代码,

var jsonString='{"foo":"json", "bar":100, "nest":{ "foobar":true }}';
var jsonObj = JSON.parse(jsonString);
//接着就能方便的使用
jsonObj.foo
jsonObj.nest.foobar

代码中的jsonObj是动态类型,在.net中,我们也可以反序列化Json,但都需要指定反序列化后的对象类型。

比如使用Json.Net

Newtonsoft.Json.JsonConvert.DeserializeObject(json, typeof(employee))

有没有办法和js一样,反序列化一个dynamic类型来方便的访问Json数据?

下面先来看看DynamicObject如何使用,然后使用DynamicObject来实现我们的想法。

二,DynamicObject分析

DynamicObject有个构造函数,但是protected, 也就是我们没有办法直接实例化来使用它。只能是通过继承来构造DynamicObject的对象。

同时DynamicObject中很很多标记为Virtual的方法,比如:

public virtual bool TryGetMember(GetMemberBinder binder, out object result);

public virtual bool TrySetMember(SetMemberBinder binder, object value);

当我们写个类继承DynamicObject, 这个动态类型类的对象,所具有的特性,就是通过重写这些virtual方法体现出来的。

假设SampleObject 是继承DynamicObject的类,那么

如果我们重写了TryGetMember, 在调用 int number = sampleObject.Number.时,就会调用TryGetMemeber方法来得到返回值。

如果我们重写了TrySetMember,在调用sampleObject.Number = number 时使用,就会调用TrySetMember方法。

了解了DynamicObject, 我们的路线就更加清晰了:

我们要写一个类DynamicJson,继承自DynamicObject

DynamicJson有静态Parse方法,接受一个Json的字符串,返回DynamicJson的对象。

DynamicJson重写TryGetMember方法,这样当访问属性的时候,我们处理,返回正确的值。

三,DynamicJson代码

DynamicJson正是这个思路实现的,下面来分析一下DynamicJson中一些关键代码

Parse静态方法

这段代码非常容易理解,这里将json以xml方式处理,属性变成了xml中的element处理

public static dynamic Parse(string json)
{
using (var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.Unicode.GetBytes(json), XmlDictionaryReaderQuotas.Max))
{
return ToValue(XElement.Load(reader));
}
}

ToValue方法

To value方法根据json反序列化后的xml信息,获取element的type属性,然后根据属性分别处理。

如果是非数组和object类型,就直接返回。

如果是,就返回DynamicJson对象,这样当我们使用对象的属性,就会调用TryGetMember方法

private static dynamic ToValue(XElement element)
{
var type = (JsonType)Enum.Parse(typeof(JsonType), element.Attribute("type").Value);
switch (type)
{
case JsonType.boolean:
return (bool)element;
case JsonType.number:
return (double)element;
case JsonType.@string:
return (string)element;
case JsonType.@object:
case JsonType.array:
return new DynamicJson(element, type);
case JsonType.@null:
default:
return null;
}
}

TryGetMember方法

下面是重写的TryGetMember方法

public override bool TryGetMember(GetMemberBinder binder, out object result)
{ //根据访问的属性,在序列化的xml结构中寻找子element.
var element = xml.Element(binder.Name); if (element == null)
{
result = null;
return false;
} result = ToValue(element);//如果存在该element, 就继续调用ToValue, 如果是普通类型,就能够返回具体的内容,如果是数组或object,就在返回一个DynamicJson对象。
return true;
}

四,总结

DynamicJson的代码实现的功能很多,详细的DynamicJson的代码,可以通过Nuget获取。

通过继承DynamicObject类,实现了非常多的功能类,

有针对Json的DynamicJson,还有针对xml的DynamicXml

使用它们,减少了不必要的类型定义,增加了程序代码的灵活性。

理解C# 4 dynamic(3) – DynamicObject的使用的更多相关文章

  1. 理解C# 4 dynamic(4) – 让人惊艳的Clay

    Clay非常类似于ExpandoObject, 可以看做是ExpandoObject的加强版. 它们能够让我们在不需要定义类的情况下,就构建出我们想要的对象.Clay和ExpandoObject相比, ...

  2. 理解C# 4 dynamic(4) – 让人惊艳的Clay(转)

    作者:Justrun名字来自<阿甘正传>,是希望自己能够更更傻一点. link: http://www.cnblogs.com/JustRun1983/p/3529157.html   理 ...

  3. 理解C# 4 dynamic(2) – ExpandoObject的使用

    ExpandoObject的使用非常简单,很容易入手.上一篇里面已经有详细的介绍了,可以看这里(理解C# 4 dynamic(1) - var, object, dynamic的区别以及dynamic ...

  4. 理解C# 4 dynamic(1) - var, object, dynamic的区别以及dynamic的使用

    阅读目录: 一. 为什么是它们三个 二. 能够任意赋值的原因 三. dynamic的用法 四. 使用dynamic的注意事项 一. 为什么是它们三个? 拿这三者比较的原因是它们在使用的时候非常相似.你 ...

  5. [转]理解C# 4 dynamic(1) - var, object, dynamic的区别以及dynamic的使用

    阅读目录: 一. 为什么是它们三个 二. 能够任意赋值的原因 三. dynamic的用法 四. 使用dynamic的注意事项 一. 为什么是它们三个? 拿这三者比较的原因是它们在使用的时候非常相似.你 ...

  6. var, object, dynamic的区别以及dynamic的使用

    var, object, dynamic的区别以及dynamic的使用 理解C# 4 dynamic(1) - var, object, dynamic的区别以及dynamic的使用 2013-06- ...

  7. C#中的var和dynamic

    在理解var和dynamic关键字之前,让我们先了解一下编程语言的类别. C#中有两类编程语言: 静态类型语言类别 动态语言类别 静态类型语言 静态类型语言也被称为强类型语言.所谓强类型语言,通俗的讲 ...

  8. 算法-动态规划 Dynamic Programming--从菜鸟到老鸟

    算法-动态规划 Dynamic Programming--从菜鸟到老鸟      版权声明:本文为博主原创文章,转载请标明出处. https://blog.csdn.net/u013309870/ar ...

  9. [LeetCode] 329. Longest Increasing Path in a Matrix_Hard tag: Dynamic Programming, DFS, Memoization

    Given an integer matrix, find the length of the longest increasing path. From each cell, you can eit ...

随机推荐

  1. 【Java EE 学习 80 上】【WebService】

    一.WebService概述 什么是WebService,顾名思义,就是基于Web的服务,它使用Http方式接收和响应外部系统的某种请求,从而实现远程调用.WebService实际上就是依据某些标准, ...

  2. gulp

    npm install -g gulp // 全局安装gulp 是为了执行 gulp 任务npm install gulp --save-dev // 本地安装gulp 是为了调用 gulp 插件 - ...

  3. SMARTY模板中如何使用get,post,request,cookies,session,server变量

    {$smarty}保留变量不需要从PHP脚本中分配,是可以在模板中直接访问的数组类型变量,通常被用于访问一些特殊的模板变量.例如,直接在模板中访问页面请求变量.获取访问模板时的时间戳.直接访问PHP中 ...

  4. sql基础大全

  5. Kafka vs RocketMQ——多Topic对性能稳定性的影响-转自阿里中间件

    引言 上期我们对比了RocketMQ和Kafka在多Topic场景下,收发消息的对比测试,RocketMQ表现稳定,而Kafka的TPS在64个Topic时可以保持13万,到了128个Topic就跌至 ...

  6. 前端弹出层框架layer

    http://www.layui.com/doc/modules/layer.html#layer.confirm

  7. 详细讲述MySQL中的子查询操作 (来自脚本之家)

    继续做以下的前期准备工作: 新建一个测试数据库TestDB: ? 1 create database TestDB; 创建测试表table1和table2: ? 1 2 3 4 5 6 7 8 9 1 ...

  8. 写给Git初学者的7个建议

    [原文] - http://blog.jobbole.com/50603/ 当我刚刚开始使用Git的版本控制时,我根本不确定我付出那么多时间是不是会得到回报.Branch.Stage.Stash,这些 ...

  9. 未能加载文件或程序集“Microsoft.ReportViewer.WinForms 解决办法

    异常信息: 未能加载文件或程序集“Microsoft.ReportViewer.WinForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken= ...

  10. 织梦cms更新新建的栏目提示:DedeTag Engine Create File False:C:/phpStudy/WWW/

    这个问题怎么解决呢?只是更换了一下栏目名称.增加了新的栏目,结果就不行了. 问题原因: 新建的栏目没有"列表命名规则",导致cms解析的时候,出现解析错误. 解决办法 在下图填入: ...