引言

类型转换经常遇到,最常用的应该是string类型转换为其它基元类型,常见于http参数类型转换。Convert静态类的Convert.ChangeType()方法可以把实现IConvertible接口的类型转换为其它也实现这个接口的类型,也等同于里面的ToInt32()、ToDecimal()等方法的功能,但不支持转换到这类型的可空类型,因为Nullable<>类型并没有实现IConvertible这个接口;此外JavaScriptSerializer.ConvertToType()这个方法相对强大,支持转换到Nullable<>类型、字符串到枚举,也支持IDictionary<string,object>类型转换为对象,居于原因,是为了JavaScriptSerializer在反序列化JSON为动态类型后,能把这些类型进行转换为常见类型,但JavaScriptSerializer.ConvertToType方法不能扩展。

神器来了

名称:

今天主角转换器叫Converter,这是花费我几天时间才琢磨出来。

点再下载代码(也要点个赞哦)

功能:

今它支持基础类型、decimal、guid和枚举相互转换以及这些类型的可空类型和数组类型相互转换,支持字典和DynamicObject转换为对象以及字典和DynamicObject的数组转换为对象数组。

扩展性:

可以增加其它类型转换,或修改某种转换规则,也就是说转换器是支持功能部分重写和功能扩展的,功能移除也支持,比如想干掉DynamicObject类型的转换也可以。

神器使用方法

1、使用静态方法,Converter.Cast(object value,Type targetType)或其泛型方法 :Converter.Cast<int?[]>(new[] {null, "2" }

2、实例化来调用,new Converter().Convert(new[] { null, "2" }, typeof(int?));

Converter的扩展

扩展是灵魂,如果没有扩展功能,这东东和JavaScriptSerializer.ConvertToType()有啥区别,Converter在扩展方面下了一翻功夫。转换器里包含多个转换单元,这些单元可以增加、删除、替换和调整顺序,自定义的单元,可以从已有单元派生,也可以完整实现,然后插入到转换器的转换单元管理器中,转换器就升级了。而转换单元本身也能调用转换器来转换,这就形成一种可扩展的递归。

关系代码如下:

 /// <summary>
/// 类型转换
/// </summary>
public Converter()
{
this.Items = new ContertItems()
.AddLast<NoConvert>()
.AddLast<NullConvert>()
.AddLast<PrimitiveContert>()
.AddLast<NullableConvert>()
.AddLast<DictionaryConvert>()
.AddLast<ArrayConvert>()
.AddLast<DynamicObjectConvert>();
}

转换器由转换单元组成

 /// <summary>
/// 定义类型转换单元
/// </summary>
public interface IConvert
{
/// <summary>
/// 将value转换为目标类型
/// 并将转换所得的值放到result
/// 如果不支持转换,则返回false
/// </summary>
/// <param name="converter">转换器实例</param>
/// <param name="value">要转换的值</param>
/// <param name="targetType">转换的目标类型</param>
/// <param name="result">转换结果</param>
/// <returns>如果不支持转换,则返回false</returns>
bool Convert(Converter converter, object value, Type targetType, out object result);
}

转换单元可以调用转换器

删除转换单元:

var converter = new Converter();
converter.Items.Remove<DynamicObjectConvert>();

增加转换单元:

编写一个单元,实现IConvert接口,比如 class JObjectConvert:IConvert{},然后就可以把这个转换单元添加到转换器实例中,

var converter = new Converter();
converter.Items.AddFrist<JObjectConvert>();

转换单元重写:

比如从string转换为decimal类时,要求5位小数,我们可以写一个单元,class MyPrimitiveContert:PrimitiveContert{},然后改写里面的Convert方法,再把MyPrimitiveContert替换转换器里的PrimitiveContert单元

var converter = new Converter();
converter.Items.Replace<PrimitiveContert, MyPrimitiveContert>();

后记

之所以写这个东西,是因为我的NetworkSocket组件里websocket部分很需要一个灵活的类型转换器,客户端发送{api:"login",parameters:[{account:"admin",password:"123456"}]}这样结构的Json给服务器,服务要解析这个json然后反射执行Login(Userinfo user)这个方法。

这里parameters数组里内容的类型是根据api的名称而定的,而要解析到api的内容,又要知道整个json的结构,形成蛋和鸡。只有将json解析为动态类型,才能满足要求,而JavaScriptSerializer反序列化为动态类型时,实际上是json对象转换为字典,json数组转换为ArrayList,其它基本类型差不多一一对应,枚举类型看情况;如果使用Json.Net解析,json对象转换为JObject动态类型,json数组转换为JArray,一些基本类型一般会对应JValue。

当把序列化和反序列化抽象或定义为接口的时候,JavaScriptSerializer.Converter方法就无力了,它没法转换JObject这些类型,也没有扩展的入口点,还有就是在.net core上也用不了。而Converter只需要添加一个单元转换单元,用来实现Json.Net里面几个动态类型转换为Api参数的类型,就可以达到完美的转换效果。

.Net下一个类型转换神器的更多相关文章

  1. Go将统治下一个10年?Go语言发展现状分析

    “本文是国内Go语言大中华区首席布道师——许式伟,在QCon2015上海站上的分享.他预测Go语言10年内一定会超过C和java,并且统治这一个10年. Go语言语法及标准库变化 Go从1.0版本到现 ...

  2. [LeetCode] Next Permutation 下一个排列

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  3. Javascript JQuery获取当前元素的兄弟元素/上一个/下一个元素(转)

    var chils= s.childNodes; //得到s的全部子节点 var par=s.parentNode; //得到s的父节点 var ns=s.nextSbiling; //获得s的下一个 ...

  4. SQL Server获取自增列下一个Id

    IDENT_CURRENT('TableName')为当前的最大标识值,IDENT_INCR('TableName')为设置的标识值增量, 两者相加即为下一个标识值 SELECT IDENT_CURR ...

  5. JMeter 将上一个请求的结果作为下一个请求的参数——使用正则提取器(转载)

    在接口测试和压力测试过程中,经常会将几个流程串联起来才能测试.如:我要进行获取用户信息接口测试,我就要先登录成功后,才能获取用户信息.所以,我就要首先要登录,获得我的登录凭证(tokenId或tick ...

  6. 获取当前时间UTC时间的下一个15分钟时间点

    ZonedDateTime zdt = ZonedDateTime.now(ZoneOffset.UTC); int now15Minute = zdt.getMinute() / P15MINUTE ...

  7. NASA的下一个十年(译)

    原文 MICHAEL ROSTON (New York Times) 从左起:木卫二:土卫六:经过火星的水手谷星的合成图:金星的拼接图 大多数人已经从人类第一次近距离看到冥王星的兴奋中冷静下来.下一个 ...

  8. SQL Server获取下一个编码字符串的实现方案分割和进位

        我在前一种解决方案SQL Server获取下一个编码字符实现和后一种解决方案SQL Server获取下一个编码字符实现继续重构与增强两篇博文中均提供了一种解决编码的方案,考虑良久对比以上两种方 ...

  9. SQL Server获取下一个编码字符实现继续重构与增强

        我在SQL Server获取下一个编码字符实现的博文中,虽然实现了这个问题,但是感觉维护起来比较麻烦,例如如果调整编码字符串的固定长度,就需要变更三个函数,这样的为何成本确实比较大.面向对象编 ...

随机推荐

  1. 《java JDK7学习笔记》之跨平台与路径设置

    Platforms表示Solaris.Linux.Windows各种操作系统平台,在这些平台上架构了java Virtaul Machine,简称JVM,Java虚拟机. Java虚拟机可以让java ...

  2. DateTime的精度小问题

    一般来说判断时间的话,用个DateTime类型就已经够用了.但是有些情况,比如下面这种 DECLARE @DT1 DATETIME DECLARE @DT2 DATETIME SELECT @DT1 ...

  3. Java的String.valueOf 转换 与、空串+类型变量转换与封装类(Integer)的toString方式转换比较。

    1.空串+类型变量方式转换 int i=20; String s=""+i; 这种方式实际上经过了两个步骤,首先进行了i.ToString()把 i 转换为 字符串,然后再进行加法 ...

  4. history

    history用来显示最近执行的命令,系统中将当前的允许的最大保存的历史命令条数保存在环境变量HISTSIZE中,缺省选项时表示显示最多HISTSIZE个命令,可以指定显示最近的n条命令 $histo ...

  5. 理解linux and inode

    inode是一个重要概念,是理解Unix/Linux文件系统和硬盘储存的基础. 我觉得,理解inode,不仅有助于提高系统操作水平,还有助于体会Unix设计哲学,即如何把底层的复杂性抽象成一个简单概念 ...

  6. 仿哔哩哔哩应用客户端Android版源码项目

    这是一款高仿哔哩哔哩安卓客户端,跟官方网的差不多吧,界面也几乎是一样的,应用里面也加了一些弹出广告,大家可以参考一下吧,安装测试包在源码文件那里,大家可以多多参考一下. 哔哩哔哩弹幕网是国内知名的弹幕 ...

  7. 记一次ganglia的故障分析 mem_report不显示

    ganglia集群中mem_report不能正确显示,有的显示有些不显示. 我通过web开发工具F12,获取生成图片的路径,然后加上&debug=3 显示发现: No matching met ...

  8. java中有类似C#里ref或out的功能吗?

    JAVA中都是值传递.JAVA中的“引用”和C++中的引用有本质的区别,倒是和C++中的指针非常类似.可以将JAVA的引用理解为“不支持指针运算的指针”.所以可以说JAVA中其实并不存在真正的引用,所 ...

  9. 在Ubuntu14.04下安装vsftp服务器

    猜想在Ubuntu下搭建ftp服务器来实现windows和ubuntu下文件互传是一件很简单的事儿,但是在网上找了好几篇文章都不行,故自己在这里总结一下方法. 首先安装vsftp服务器 sudo ap ...

  10. java 26 - 9 网络编程之 TCP协议多用户上传文件

    TCP实现多用户上传文件: 需要同时给多用户上传文件,这样就得用多线程来实现. 实际上,这样的话,上传的先后顺序和速度就跟客户端的带宽有关:带宽够,就容易抢占到线程的执行权: 首先,创建个线程类:(这 ...