新框架正在逐步完善,可喜可贺的是基础服务部分初具模样了,给大家分享一下

由于基础服务涉及面太广,也没开发完,这篇只介绍其中的类型转化部分,命名为类型转化基础服务,其实就是基础服务模块的类型转化子模块

说到类型转化必须要弄清楚.net的类型,类型都不清楚何来类型转化

1、Primitive类型

1.1 这个概念估计很多人都没听说过,Primitive不是一个新类型,而是.net类型中最基本的一种分类,是基元类型的意思

        MS将类型分为三类:Primitive(基元类型)、Complex(复合类型) 和 Collection(集合类型),Type 提供了IsPrimitive 属性

1.2 哪些类型属于Primitive呢?

参考链接:http://msdn.microsoft.com/en-us/library/system.type.isprimitive(v=vs.110).aspx

”The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single.“

1.3 看到这里还是挺失望的,我们常用的类型Decimal和String并不含在内

有的同学可能说,别说那两个了,里面就除了Char和Double其他都没用过;老实说MS真的把.net程序员彻底惯坏了

其实Boolean就是我们常用的bool,Int32就是int,Int64就是long,Single就是float

   

1.4 Primitive类型有什么用呢?

Primitive是基元类型,可以这样理解,其他类型都是由Primitive类型构成的或者衍生的,.net对Primitive支持最好,"有些地方"对于非Primitive类型支持不好,可能造成"灵异"事件(对于一般的项目是很难碰到的,如果你能碰到,说明你对.net钻研的比较深了,普通的工程师就更不要嚷嚷说.net类型有缺陷不敢用之说,最多底层框架开发者或者架构师小心一点)

   这里就不展开了

2、IConvertible类型

  IConvertible并不是新维度的类型类别,IConvertible是MS定义的一个重要接口,我这里讲的IConvertible类型特指Ms定义的基本类型中继承了该接口的类型

  我来稍作解析一下,继承了IConvertible的类型非常强大,可以方便的转化为常用的这15种类型,也正是这15种类型继承了IConvertible接口

  也就是这15种类型可以方便的相互转化(其实不一定的,有些转化是会出错的)

IConvertible类型转化具有高度的扩展性,可以传一个格式化的参数(IFormatProvider)

注:在我看来IFormatProvider主要是作用是字符串(string)类型和其他14种类型相互转化之用,string被Ms定义成了"通用类型",我认为是数据形态之一(我把数据分成几个形态,强类型,弱类型(object),string,二进制(byte[]),数据流(Stream),这个会在序列化基础服务中再详细讲解)

3、IFormattable类型

IFormattable和前面IConvertible类似,也是Ms定义的一个重要接口,继承这个接口的类型非常多,这个接口主要是把对象转化为特殊(格式化)的字符串。

基本类型中的byte\DateTime\Decimal\Double\short\int\long\sbyte\float\ushort\uint\ulong等都继承,除此之外还有很多系统类型也都继承IConvertible(这里不再枚举),我们自定义类型也可以方便的实现IConvertible接口

鉴于字符串(string)的重要性,该接口相关的服务对应用开发非常有用(但是很多人都不清楚)

4、"基本"类型

这里是我定义的”基本类型“,我认为有这些类型就足够开发使用,框架对此之外的类型不予"支持",或者这些类型优先支持

包含类型列表:bool、byte、char、decimal、double、float、int、long、string、DateTime、byte[]

注1:在现在内存这么便宜的时代,我认为短数据类型的作用不大,短数据类型都使用int就好了

注2:我也不喜欢使用无符号类型,所以又省略了一大批类型,对于数字类型Ms使用==0表示"逻辑空",我使用<=0表示"逻辑空",后面还有相关例子

注3:这样做也是情非得已,类型太多了,其排列组合更多,好在本框架是可扩展框架,使用本框架的时候可以自己扩展支持的类型,当然也可以开发一个类型扩展的组件(类库),需要的时候自己注册进去


现在开始演示类型转化基础服务

一、基本类型转化

1、类型太多,先测试字符串转int

2、不同数字类型转化为Int

这里我要多唠叨一句,我前面说过对”基本类型“以外的不予支持,其实是不"支持"转化为这些类型,这些类型转化为”基本类型“是没有问题的

上面例子里面有小数(浮点)转整数(int)的例子,Ms有自己的一套“四舍五入”的规则,如果不满意可以自己扩展注册进去(一般情况下调用的地方并不需要修改)

另外,会尝试IConvertible的类型相互转化,如果Ms支持的很好的IConvertible转化.这里也没道理不支持的

3、object转化为int

以上例子可以看出,基本类型转化完全没有问题,其实在主框架,我也不打算默认实现复杂自定义类型的转化,这个留给扩展实现

有人可能会说你上面的这些功能So easy,实现过类似功能的多如牛毛,不过是多造个轮子而已。确实,基本类型转化实现简单,但是这里要强调,我做的是可扩展框架,可扩展是亮点,而且非常容易扩展

二、自定义类型转化为基本类型

1、先看自定义类型代码

非常简单还是解读一下,定义了两个类型,customObj明显是个模型(Model)类,customConverter有一个方法传入一个customObj对象返回一个int值

2、再看对象转化代码

首先我们看结果,是我们预期的效果,和customConverter的Get方法的效果一致,但是我们没有直接调用customConverter.Get,甚至好像和customConverter类型都没什么关系

这里有几个关键因素,其一是GlobalServices.Convert方法是怎么运行的;其二是GlobalServices.CreateContainer()是什么鬼

三、源码解析

1、GlobalServices.Convert方法解析

这个类型转化还是挺复杂的,挑主要的来解读

1.1 TryConvert是尝试类型转化,如果转化失败可以换一种方法再做

这种方式在本框架中有大量应用,其实就就形成一个”策略链“,每个”策略“判断一个这个问题自己是否是自己可以处理的类型,不能处理,下一个策略继续,这样非常便于扩展

在TryConvert中先调用个接口IEntityConvert,转化失败再调用IEntityAccess用来转化

这里有一个特别重要的事情,就是这个接口的对象从哪里来,这里是来自一个容器对象,这里很清楚的看到本框架的一个扩展点,只要往容器里面添加"策略"就可以增强本框架的类型转化功能,这是我为什么说主框架不打算实现复杂的类型转化,真的非常容易扩展

1.2 再看Convert主方法

A:先按当前类型尝试转化

如果策略库(容器注册)里面有当前两种类型转化的策略,性能是最好的,优先执行

B:转化失败判断当前对象是否为空

  对象为null,放弃转化,直接返回默认值

C:Transform.TryConvertByType

  这个简单就是强制类型转化,如果T是S的基类,这个时候就可以直接转化过去,也是非常安全的

D:再尝试IConvertible转化

前面说到系统的IConvertible定义了15种基本类型的相互排列组合转化,而且还可以使用IFormatProvider自定义转化,这就是一个强大的转化机器,不能不试

E:再检测返回类型是否为string,如果是string直接调用对象的ToString()

F:尝试通用类型转化(IConvert)

  这个地方可以把第三方的Mapper工具封装为IConvert接口注册进来(后面还有讲解)

G:最后尝试把s对象转化为字符串,然后把字符串转化为目标类型(T)对象

其实这里把字符串作为基本数据格式,相当于与对s对象序列化为字符串,然后把字符串反序列化为T类型对象,也不怪我怎么用,.net所有类型都有一个ToString()方法,所以string是个不错的中间类型

功能是不是非常强大,也非常有别于很多类型转化工具,上来先反射,获取类型元数据,然后调用属性和字段,现在还没做测试,我这种方式可能会有明显的性能优势,但是性能现在不是我最想考虑的问题,我现在考虑的是怎么可以非常简单的扩展

2、GlobalServices.CreateContainer()是什么鬼

CreateContainer定义

A:从上面可以看出GlobalServices.CreateContainer就是一个再普通不过的容器,默认实例的容器名是GlobalServices

B:前面有提到容器是可以扩展的,只要我们使用的容器支持(比如Unity、Spring.net等),我们完全可以使用配置文件来扩展类型转化,还可以使用非常炫的IOC和AOP等特性

C:说到这里,现在"业界"有几个类型转化工作可以做到?我稍微看了一个现在非常流行的Automapper,自定义映射确实没问题,但是映射过程还可以通过配置文件扩展或者IOC和AOP的我没见识过,如果有人看到过请告知,我要好好学习学习

D:早期看过这篇文章的可能发现,变化很大,我把GlobalServices由静态类修改可以实例化的形式,这样就允许我们创建多套服务配置管理对象(使用子容器技术,继承默认服务并覆盖少数服务),进一步提高可扩展性

3、其实GlobalServices容器和其他容器还是有点区别的,继续深挖源码

这里有一个不起眼的地方加了一行代码,给GlobalServices容器”吃小灶“

不挖不知道,一挖吓一跳,有一种”柳暗花明又一村“的感觉

哈哈,我就说我要对每个容器做包装,”居心不良“吧;哈哈,这样说太难听了,一句话"还是为了更好的扩展"。

4、没办法了,还得继续挖GlobalServices.CheckServices

这里可以看到框架支持的"基本类型",把这些转化策略都注册到容器中,主要是担心容器注册的服务不够用,把不足的基本类型转化服务都注册上

当然如果容器中已经存在同类型的"服务",这里的注册是会忽略的

同样,就算是这里注册的服务,如果觉得不好用,也可以在外面重新注册并覆盖

还有一点,前面截图可以明显看出"基础服务模块"的基本样子,但是除了”类型转化子模块“外,其他子模块都还没开发出来

四、拆分使用

1、字符串转时间测试

以上两个日期字符串我们用来转化为时间,一个成功一个失败

这个例子我想说明两个问题

其一、每个对象转化服务都可以单独使用而且性能最好,省去了复杂的的策略逻辑、容器操作,而且执行逻辑明确

其二、使用特定的服务不便于扩展,如果这样的代码有bug需要替换,每个地方去改,很容易导致遗留问题(没改全)

其三、通用服务都是默认实现,总有局限性,有些特殊问题无法解决(以上调用逻辑和使用全局服务的逻辑一致,也会出现异常),总有特事特办的,只要控制数量还是没有问题的

2、对特殊字符串转转时间测试

以上顺利转化成功,可喜可贺,事实上有的时候特事特办能做到更高的性能或者更好的效果

这里还有一个我要说的就是“面向对象编程”,在我看来很多人都是在做"面向类"编程,因为他们的类型都只有一个实例或者都只能简单的new()来构造,我特别强调类和对象是一对多的关系,一个类可以初始化多个对象,通过不同的字段和属性能达到不同的效果。这样才可以把类和对象用到极致。不是有句名言“程序等于算法加数据结构”。对我而言,每个对象就是一个独立的程序,字段(属性)就是数据结构,定义的方法(函数)就是算法。好的对象是可以独立迁移的。如果使用容器配置管理,我要迁移程序(组件对象)就只要复制对应的配置节点和dll即可。

当然不是说一定非要硬编码,这样的“特事特办”也可以在容器中配置特殊的节点来实现

3、从容器中获取特殊服务对特殊字符串转转时间测试

效果还不错吧,而且也是面向接口的,要扩展也是非常简单

以下是容器配置:

以上是Unity容器配置,能实现类似配置的容器很多,选择也很多,再强调一次逻辑代码没有必要强依赖任何固定的容器

五、IFormattable转化为字符串服务

1、时间格式化的例子

效果不错吧

有人说使用DateTime的ToString()方法传一个字符串参数吗?确实,底层调用的是同一个逻辑。

我们知道DateTime的ToString()可以传一个格式字符串,那这个格式字符串硬编码写死不太好吧,如果哪天我们要的字符串格式使用ToString()无法实现怎么办。ToString(format)是一种转化字符串的方式,但不是唯一的方式。 这就是面向接口的好处,我们依赖的是把一个把DateTime转化为string的服务(接口),甚至是一个把object转化为string的服务。这样我们的服务就更强大,更容易扩展了。

2、使用容器再做一个上面的例子

效果和前面一样

以下是容器配置:

当然还可以注册为全局服务(使用GlobalServices.Convert就可以调用到,覆盖默认的ToString()),这样就更方便了(但是要慎重,全局格式一定定义的足够通用)

六、扩展性演示

1、逻辑空(int转bool)

前面有提到,我是把>0为true的,<=0为false,我一直用的很方便,我叫做"逻辑空",但是ms并不是这样处理的,如果有的团队还是希望按ms的规则怎么办,扩展啊

2、把上例中的注释打开就切换为ms模式(==0为false)的扩展

上面的结果就是ms模式了

3、现在来看一下是怎么扩展的

以上代码很清楚,扩展很简单,获取服务配置的容器,注入服务并覆盖原服务,就完成了扩展

当然如果自己想扩展基础服务中的任何功能都不是问题,只需要实现对应服务接口,如后注册到服务容器中去就可以了

七、IConvertible转化功能

1、IConvertible转化int的例子

A:这里演示的就是IConvertible(15种类型)转化为int的部分例子,完全没有问题,调用也很方便

B:有的人可能会说,Ms提供了IConvertible搞定15中类型相互转化,你写那些类型转化完全是重复造轮子,这是没有理解这个框架的思想

注:在这里使用Convert<IConvertible, int>转化short类型的值(123)是没有使用Convert<short, int>性能好的,不仅仅是类型转化的问题,完全不是一套逻辑

C:这个框架(可扩展)不只是提供某种功能,他要提供高度可扩展性,以便对任意的细分"领域"都可以扩展优化效果和性能

D:特别是性能这块,框架优先获取最细分领域的服务来处理问题,我有一个开发思想,通用工具解决大部分(60%到90%)的问题,有特殊性能或业务需求的单独写代码来支持,这个框架就是对这种思想的强有力支持

注:这个框架和其他框架有个明显的区别,一般框架是越扩展(打补丁)性能越差,这个框架是相反的,一般情况下是越扩展性能越好(除非扩展进来的服务太差,那还叫扩展吗)

八、自定义类型转化

1、继承类型转化试试

木有问题,转化成功

2、取消继承再测

“哦,NO!框架出bug了,这么简单的事情也出错”

不是的,大家好好看这个错误信息的内容,可扩展框架提醒你,需要扩展

3、按提示的扩展IEntityConvert再测

又转化成功了,说明可扩展此言不虚

有人说你这不就是硬编码吗?类型转化这等小事,还要一个个硬编码,还让不让人活了。我还要重复一遍,对于特别性能需要的地方,硬编码是有必要的

而诶硬编码类型转化代码不需要你直接调用,是注入到框架中的,调用的地方没有区别(不知道是调用硬编码实现还是默认实现)

有人说你要我每个类型都硬编码就是不对,现在没有这么干的!确实没有必要,90%以上的类型转化都不需要硬编码,再按提示做另一种扩展

4、扩展IConvert再测

再次转化成功,可以使用这种方式扩展自定义类型的默认转化

有人要挑错了,你以上代码哪是任意类型嘛,明明就只能A转B,其他都转成null了。以上只是个示例,现在开源项目中能实现这样转化的工具很多,我真没必要开发到主框架中,拿来用就可以了

我完全可以拿Automapper(或者EmitMapper,LiteMapper等)封装一下,继承IConvert接口,然后注册到框架中来,这才是本框架的精神(集成和整合),还是那句话,如果特定两个类型转化需要高性能,直接硬编码注册进来,所有调用的地方不用改就达到优化的目的

我也不用再纠结哪个Mapper更好,所有Mapper都封装,爱用哪个就注册哪个(当然不建议同一个应用程序使用两个以上的Mapper)

类型转化基础服务基本介绍完了,还有遗漏的我再补(大块应该都差不多了),后面的精力将转为其他模块的开发和介绍。有什么建议和意见请回复,谢谢。

Asp.net 面向接口可扩展框架之类型转化基础服务的更多相关文章

  1. Asp.net 面向接口可扩展框架之使用“类型转化基础服务”测试四种Mapper(AutoMapper、EmitMapper、NLiteMapper及TinyMapper)

    Asp.net 面向接口可扩展框架的“类型转化基础服务”是我认为除了“核心容器”之外最为重要的组成部分 但是前面博文一出,争议很多,为此我再写一篇类型转化基础服务和各种Mapper结合的例子,顺便对各 ...

  2. Asp.net 面向接口可扩展框架之核心容器(含测试代码下载)

    新框架的容器部分终于调通了!容器实在太重要了,所以有用了一个名词叫“核心容器”. 容器为什么那么重要呢?这个有必要好好说道说道. 1.首先我们从框架名称面向接口编程说起,什么是面向接口编程?(这个度娘 ...

  3. Asp.net 面向接口可扩展框架之业务规则引擎扩展组件

    随着面向接口可扩展框架的继续开发,有些功能开发出现了"瓶颈",有太多的东西要写死才好做.但写死的代码扩展性是非常的不好,迷茫中寻找出入... 进而想到我以前开发的好几个项目,都已有 ...

  4. Asp.net 面向接口可扩展框架之消息队列组件

    消息队列对大多数人应该比较陌生.但是要提到MQ听说过的人会多很多.MQ就是英文单词"Message queue"的缩写,翻译成中文就是消息队列(我英语差,翻译错了请告知). PS: ...

  5. Asp.net 面向接口可扩展框架之应用程序上下文作用域组件

    在团队中推广面向接口开发两年左右,成果总体来说我还是挺满意的,使用面向接口开发的模块使用Unity容器配置的功能非常稳定,便于共享迁移(另一个项目使用只需要复制配置和调用接口即可),如果再配合上DI那 ...

  6. Asp.net 面向接口可扩展框架之“Mvc扩展框架及DI”

    标题“Mvc扩展框架及DI”有点绕口,我也想不出好的命名,因为这个内容很杂,涉及多个模块,但在日常开发又密不可分 首先说Mvc扩展框架,该Mvc扩展就是把以前的那个Mvc分区扩展框架迁移过来,并优化整 ...

  7. Asp.net 面向接口可扩展框架之数据处理模块及EntityFramework扩展和Dapper扩展(含干货)

    接口数据处理模块是什么意思呢?实际上很简单,就是使用面向接口的思想和方式来做数据处理. 还提到EntityFramework和Dapper,EntityFramework和Dapper是.net环境下 ...

  8. 面向接口可扩展框架之“Mvc扩展框架及DI”

    面向接口可扩展框架之“Mvc扩展框架及DI” 标题“Mvc扩展框架及DI”有点绕口,我也想不出好的命名,因为这个内容很杂,涉及多个模块,但在日常开发又密不可分 首先说Mvc扩展框架,该Mvc扩展就是把 ...

  9. net 面向接口框架

    Asp.net 面向接口框架之应用程序上下文作用域组件 在团队中推广面向接口开发两年左右,成果总体来说我还是挺满意的,使用面向接口开发的模块使用Unity容器配置的功能非常稳定,便于共享迁移(另一个项 ...

随机推荐

  1. HaProxy+Keepalived+Mycat高可用群集配置

    概述 本章节主要介绍配置HaProxy+Keepalived高可用群集,Mycat的配置就不在这里做介绍,可以参考我前面写的几篇关于Mycat的文章. 部署图: 配置  HaProxy安装 181和1 ...

  2. 论HTML5 Audio 标签歌词同步的实现

    HTML5草案里面其实有原生的字幕标签(<track> Tag)的,但使用的是vtt格式的文件,非常规的字幕(.sub, .srt)或歌词文件(.lrc). 用法如下(代码来自W3Scho ...

  3. Java接口总结

    接口的定义: 使用interface来定义一个接口.接口定义与类的定义类似,也是分为接口的声明和接口体,其中接口体由变量定义和方法定义两部分组成,定义接口的基本语法如下: [修饰符] interfac ...

  4. Atitit.自然语言处理--摘要算法---圣经章节旧约39卷概览bible overview v2 qa1.docx

    Atitit.自然语言处理--摘要算法---圣经章节旧约39卷概览bible overview v2 qa1.docx 1. 摘要算法的大概流程2 2. 旧约圣经 (39卷)2 2.1. 与古兰经的对 ...

  5. Atiti 数据库系统原理 与数据库方面的书籍 attilax总结 v3 .docx

    Atiti 数据库系统原理 与数据库方面的书籍 attilax总结 v3 .docx 1.1. 数据库的类型,网状,层次,树形数据库,kv数据库.oodb2 1.2. Er模型2 1.3. Sql2 ...

  6. Android笔记——Android中visibility属性VISIBLE、INVISIBLE、GONE的区别

    在Android开发中,大部分控件都有visibility这个属性,其属性有3个分别为"visible "."invisible"."gone&quo ...

  7. Android NDK开发Hello Word!

    在之前的博客中已经为大家介绍了,如何在win环境下配置DNK程序,本篇我将带大家实现一个简单的Hello jni程序,让大家真正感受一下NDK开发的魅力.这里我们选择使用C+JAVA开发Android ...

  8. sublime text学习

    Ctrl + /  ---------------------注释 Ctrl + 滚动 --------------字体变大/缩小 Ctrl + N-------------------新建 软件右下 ...

  9. Hibernate4.0之HibernateSessionFactory源码详解

    import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.cfg.Conf ...

  10. 在Linux中运行Nancy应用程序

    最近在研究如何将.NET应用程序移植到非Windows操作系统中运行,逐渐会写一些文章出来.目前还没有太深的研究,所以这些文章大多主要是记录我的一些实验. 这篇文章记录了我如何利用NancyFx编写一 ...