本系列文章将介绍一些对初学者有帮助的辅助类,这些辅助类本身并没有什么稀奇之处,如何能发现需要封装它们可能更加重要,所谓授之以鱼不如授之以渔,掌握封装公共操作类的技巧才是关键,我会详细说明创建这些类的动机和思考过程,以帮助初学者发现和封装自己需要的东西。创建公共操作类的技巧,大家可以参考我的这篇文章——应用程序框架实战十二:公共操作类开发技巧(初学者必读)

  封装公共操作类,不仅要把技术上困难的封装进来,还需要不断观察自己的代码,以找出哪些部分可以更加简化。本文将介绍一个容易被大家所忽视的东西——数据类型转换。

  数据类型转换可以把某个源类型转换为目标类型,比如把字符串转换为整型。一种选择是,你可以使用System.Convert类进行转换。  

string input = "";
int result = System.Convert.ToInt32( input);

  这样看起来好像没什么问题,不过input很明显不一定是个常量,如果你还在使用ASP.NET Web Form这样的技术,你需要在后置代码中从控件读取值。

string input = TextBox1.Text;
int result = System.Convert.ToInt32( input);

  当客户输入整数时,不会有什么问题,但他如果输入一个字母或汉字,上面代码会抛出一个异常,“System.FormatException: 输入字符串的格式不正确。”,这可能不是你想要的。当然,你可以在客户端进行JS验证,不过客户也可以绕过你的页面,直接POST到你的服务器,所以你在服务端必须处理这个问题。

  引发异常,并且你没有进行任何处理,可能导致一个黄页,让你的客户一惊。为了避免显示黄页,初学者大多直接在代码上加一个try-catch进行捕获,并给客户一个友情提示。

try {
  string input = TextBox1.Text;
  int result = System.Convert.ToInt32( input );
}
catch( Exception ex ) {
  //弹出消息框提示客户输入正确数据
}

  一旦吃到甜头,初学者发现这段代码可以实现他要的功能,不会过多考虑可维护性,于是会把这个结构向整个表现层复制,最终导致一个混乱的局面。

  除了表现层以外,数据访问层也经常需要进行数据类型转换。如果你还在使用原始的Ado.Net,从DataReader获取值。

IDataReader reader = cmd.ExecuteReader();
int result = System.Convert.ToInt32( reader["字段名"] );

  同样,为了不引发异常,初学者根据之前的经验,会在调用代码时添加try-catch进行异常捕获。

try {
  IDataReader reader = cmd.ExecuteReader();
  int result = System.Convert.ToInt32( reader["字段名"] );
}
catch( Exception ex ) {
  //有些人会在这里记录错误日志,还有些懒人直接留空,啥也不干
}

  所以最终的结果是,只要进行数据类型转换的操作,初学者为了一定的系统健壮性会大量添加异常处理结构,从而导致代码混乱。

  另一个选择是,.Net提供了一个不引发异常的类型转换方法,比如,

string input = "";
int result;
if( int.TryParse( input, out result ) == false ){
  //处理错误
}

  TryParse会返回一个bool值,指示转换是否成功,如果转换失败,你可以记录日志,并显示一个错误。不过大部分人都可能会偷懒,不会在这里进行任何处理。

string input = "";
int result;
int.TryParse( input, out result );

  如果你不想引发异常,更不想用try-catch结构来捕获异常,这确实是一个更好的选择,但需要额外定义一个变量,作为out参数来获取值,会造成额外的工作量。

  当然,.Net技术也一直处于持续改进中,表现层技术进入到MVC和WPF时代,而数据访问技术也进入到了Entity Framework时代。MVC提供了一个叫做模型绑定的功能,用于将界面上传回的数据映射到控制器操作的参数中,并且这些参数可以支持实体,这是一个非常强大的功能,这样就不需要手工进行赋值了,更不需要类型转换。WPF通过双向数据绑定,Entity Framework通过映射器,都解决了类似问题。

  但是,并不是说数据类型转换就毫无用武之地了,考虑一个使用MVC的场景。你在界面上有一个表格,表格的每行都有一个checkbox,你可以打勾以选中某些行,然后你会把每行的实体标识传到控制器。如果实体标识的数据类型使用Guid,你可以用一个IList<Guid>来接收。

public ActionResult 方法名( IList<Guid> ids ) {
}

  这一般都行得通。但是,你并不总是可以这样干,出于某些特殊原因,有时候你需要自己在js中用逗号拼接一些Id,或者用一个Hidden把用逗号拼接的Id保存起来,然后作为一个字符串传到控制器。比如” 06d8dcdd-cfad-433c-aec0-87bf613b9457, 684c0c02-93ec-4047-8f16-57e36b50d703”。

public ActionResult 方法名( string ids ) {
}

  由于没有自动转换支持,你只好自己动手,这很简单,使用逗号把输入字符串打散成字符串数组,然后遍历每个数组元素,转换成Guid类型,再添加到一个结果集合保存起来就OK了。

public ActionResult 方法名( string ids ) {
  List<Guid> result = new List<Guid>();
  string[] list = ids.Split( ',' );
  foreach( var each in list ) {
    result.Add( Guid.Parse( each ) );
  }
  //在这里把result传到业务层
}

  你发现这段代码不仅可以处理带有逗号的字符串,像” 06d8dcdd-cfad-433c-aec0-87bf613b9457, 684c0c02-93ec-4047-8f16-57e36b50d703”,甚至还能处理不带逗号的,比如“06d8dcdd-cfad-433c-aec0-87bf613b9457 “。你非常满意,然后把这一段代码复制到所有需要将拼接字符串转换成集合的地方。

  没过多久,你在一个页面发现了Bug,以前测试的时候,都是操作多个Id,这次没进行操作,传过来的字符串是””,你的代码没有进行任何健壮性检测,所以失败了,抛出一个异常“无法识别的 GUID 格式。“。

  你安慰自己“这并不算什么技术问题,只是一时疏忽,看我加一个判断,一招将它搞定“。不过在你的下意识里,已经感觉到进行边界测试才是健壮性的关键。

public ActionResult 方法名( string ids ) {
  List<Guid> result = new List<Guid>();
  if ( !string.IsNullOrWhiteSpace( ids ) ) {
    string[] list = ids.Split( ',' );
    foreach( var each in list ) {
      result.Add( Guid.Parse( each ) );
    }
  }
  //在这里把result传到业务层
}

  你现在准备测试一下,传了一个””过来,果然有效,你大赞自己处理BUG的速度惊人,为了给其它地方也添加如此健壮的特性,你打开所有可能用到的页面,找到这几行代码,进行修改,虽然你感觉这确实有点无聊,但还是只有硬起头皮改了。

  从上面可以看到,虽然是司空见惯的数据类型转换,也还是有很多值得我们改进的地方。

  下一篇我将使用TDD方式把数据类型转换公共操作类开发出来。由于TDD并不是本系列介绍的重点,所以我不会在本文中详细介绍TDD的要点,请大家查看相关资料,如果有空,我会专门写一篇文章来分享我在使用TDD所碰到的障碍以及心得。

  .Net应用程序框架交流QQ群: 386092459,欢迎有兴趣的朋友加入讨论。

  谢谢大家的持续关注,我的博客地址:http://www.cnblogs.com/xiadao521/

Util应用程序框架公共操作类(一):数据类型转换公共操作类(介绍篇)的更多相关文章

  1. Util应用程序框架公共操作类(三):数据类型转换公共操作类(扩展篇)

    上一篇以TDD方式介绍了数据类型转换公共操作类的开发,并提供了单元测试和实现代码,本文将演示通过扩展方法来增强公共操作类,以便调用时更加简化. 下面以字符串转换为List<Guid>为例进 ...

  2. Util应用程序框架公共操作类(二):数据类型转换公共操作类(源码篇)

    上一篇介绍了数据类型转换的一些情况,可以看出,如果不进行封装,有可能导致比较混乱的代码.本文通过TDD方式把数据类型转换公共操作类开发出来,并提供源码下载. 我们在 应用程序框架实战十一:创建VS解决 ...

  3. 应用程序框架实战二十一:DDD分层架构之仓储(介绍篇)

    前面已经介绍过Entity Framework的工作单元和映射层超类型的封装,从本文开始,将逐步介绍仓储以及对查询的扩展支持. 什么是仓储 仓储表示聚合的集合. 仓储所表现出来的集合外观,仅仅是一种模 ...

  4. Util应用程序框架公共操作类

    随笔分类 - Util应用程序框架公共操作类 Util应用程序框架公共操作类 Util应用程序框架公共操作类(五):异常公共操作类 摘要: 任何系统都需要处理错误,本文介绍的异常公共操作类,用于对业务 ...

  5. Util应用程序框架公共操作类(十二):Lambda表达式公共操作类(三)

    今天在开发一个简单查询时,发现我的Lambda操作类的GetValue方法无法正确获取枚举类型值,以至查询结果错误. 我增加了几个单元测试来捕获错误,代码如下. /// <summary> ...

  6. Util应用程序框架公共操作类(七):Lambda表达式公共操作类

    前一篇扩展了两个常用验证方法,本文将封装两个Lambda表达式操作,用来为下一篇的查询扩展服务. Lambda表达式是一种简洁的匿名函数语法,可以用它将方法作为委托参数传递.在Linq中,大量使用La ...

  7. Util应用程序框架公共操作类(四):验证公共操作类

    为了能够验证领域实体,需要一个验证公共操作类来提供支持.由于我将使用企业库(Enterprise Library)的验证组件来完成这项任务,所以本文也将演示对第三方框架的封装要点. .Net提供了一个 ...

  8. YTU 2618: B 求类中数据成员的最大值-类模板

    2618: B 求类中数据成员的最大值-类模板 时间限制: 1 Sec  内存限制: 128 MB 提交: 430  解决: 300 题目描述 声明一个类模板,类模板中有三个相同类型的数据成员,有一函 ...

  9. 泛型集合、datatable常用数据类型转换Json帮助类

    泛型集合.datatable常用数据类型转换Json帮助类 using System; using System.Data; using System.Configuration; using Sys ...

随机推荐

  1. web优化 js性能高级篇

    今天我们继续上一个阶段关于web的性能优化,如何对js高级进行优化 (1)闭包 何为闭包; 一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.  我认 ...

  2. Angular初步

    一.angular.js是什么? angular.js是一个javascript的框架,与jquery是一个级别的,区别是jquery主要是擅长dom操作,而angular主要是擅长绑定数据显示数据. ...

  3. Android中数据存储(一)

    国庆没有给国家添堵,没有勾搭妹子,乖乖的写着自己的博客..... 本文将为大家介绍Android中数据存储的五种方式,数据存储可是非常重要的知识哦. 一,文件存储数据 ①在ROM存储数据 关于在ROM ...

  4. mongodb的修改器

    在mongodb中通常文档只会有一部分要更新,利用原子的更新修改器,可以做到只更新文档的一部分键值,而且更新极为高效,更新修改器是种特殊的键,用来指定复杂的更新操作,比如调整.增加.或者删除键,还可以 ...

  5. Centos7 Docker 多主机 容器互连--基于OVS

    来一张自己画的图,mark:2016年6月27日17:09:14 自己理解,如有错误 多谢指教. centos7, 部署OVS和docker.以及基于centos6.8的ssh images 命令. ...

  6. Java中堆内存和栈内存详解

    Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...

  7. return array 评论添加状态和提示信息

    ThinkSNS漏洞系列第一弹,某处处理不当导致SQL注入 漏洞点出现在Comment Widget里:\addons\widget\CommentWidget\CommentWidget.class ...

  8. HDFS 异常处理与恢复

    在前面的文章 <HDFS DataNode 设计实现解析>中我们对文件操作进行了描述,但并未展开讲述其中涉及的异常错误处理与恢复机制.本文将深入探讨 HDFS 文件操作涉及的错误处理与恢复 ...

  9. Setting Up KeePass For Centos 6

    This mini-howto describes how to set up KeePass on Centos 6. It requires building mono from source a ...

  10. 业务安全通用解决方案——WAF数据风控

    业务安全通用解决方案——WAF数据风控 作者:南浔@阿里云安全 “你们安全不要阻碍业务发展”.“这个安全策略降低用户体验,影响转化率”——这是甲方企业安全部门经常听到合作团队抱怨.但安全从业者加入公司 ...