上一篇介绍了数据类型转换的一些情况,可以看出,如果不进行封装,有可能导致比较混乱的代码。本文通过TDD方式把数据类型转换公共操作类开发出来,并提供源码下载。

  我们在 应用程序框架实战十一:创建VS解决方案与程序集 一文已经创建了解决方案,包含一个类库项目和一个单元测试项目。单元测试将使用.Net自带的 MsTest,另外通过Resharper工具来观察测试结果。

  首先考虑我们期望的API长成什么样子。基于TDD开发,其中一个作用是帮助程序员设计期望的API,这称为意图导向编程。

  因为数据类型转换是Convert,所以我们先在单元测试项目中创建一个ConvertTest的类文件。

  类创建好以后,我先随便创建一个方法Test,以迅速展开工作。测试的方法名Test,我是随便起的,因为现在还不清楚API是什么样,我一会再回过头来改。

  1. using Microsoft.VisualStudio.TestTools.UnitTesting;
  2. namespace Util.Tests {
  3. /// <summary>
  4. /// 类型转换公共操作类测试
  5. /// </summary>
  6. [TestClass]
  7. public class ConvertTest {
  8. [TestMethod]
  9. public void Test() {
  10. }
  11. }
  12. }

  为了照顾还没有使用单元测试的朋友,我在这里简单介绍一下MsTest。MsTest是.Net仿照JUnit打造的一个单元测试框架。在单元测试类上需要添加一个TestClass特性,在测试方法上添加TestMethod特性,用来识别哪些类的操作需要测试。还有一些其它特性,在用到的时候我再介绍。

  现在先来实现一个最简单的功能,把字符串”1”转换为整数1。

  1. [TestMethod]
  2. public void Test() {
  3. Assert.AreEqual( , Util.ConvertHelper.ToInt( "" ) );
  4. }

  我把常用公共操作类尽量放到顶级命名空间Util,这样我就可以通过编写Util.来弹出代码提示,这样我连常用类也不用记了。

  使用ConvertHelper是一个常规命名,大多数开发人员可以理解它是一个类型转换的公共操作类。我也这样用了多年,不过后面我发现Util.ConvertHelper有点啰嗦,所以我简化成Util.Convert,但Convert又和系统重名了,所以我现在使用Util.Conv,你不一定要按我的这个命名,你可以使用ConvertHelper这样的命名以提高代码清晰度。

  System.Convert使用ToInt32来精确表示int是一个32位的数字,不过我们的公共操作类不用这样精确,ToInt就可以了,如果要封装ToInt64呢,我就用ToLong,这样比较符合我的习惯。

  现在代码被简化成了下面的代码。

  1. Assert.AreEqual( , Util.Conv.ToInt( "" ) );

  Assert在测试中用来断言,断言就是比较实际计算出来的值是否和预期一致,Assert包含大量比较方法,AreEqual使用频率最高,用来比较预期值(左边)与实际值(右边)是否值相等,还有一个AreSame方法用来比较是否引用相等。

  由于Conv类还未创建,所以显示一个红色警告。   现在在Util类库项目中创建一个Conv类。

  创建了Conv类以后,单元测试代码检测到Conv,但ToInt方法未创建,所以红色警告转移到ToInt方法。

  现在用鼠标左键单击红色ToInit方法,Resharper在左侧显示一个红色的灯泡。

  单击红色灯泡提示,选择第一项”Create Method ‘Conv.ToInt’”。

  Resharper会在Conv类中自动创建一个ToInt方法。

  1. public class Conv {
  2. public static int ToInt( string s ) {
  3. throw new NotImplementedException();
  4. }
  5. }

  方法体抛出一个未实现的异常,这正是我们想要的。TDD的口诀是“红、绿、重构”,第一步需要先保证方法执行失败,显示红色警告。至于未何需要测试先行,以及首先执行失败,牵扯TDD开发价值观,请大家参考相关资料。

  准备工作已经就绪,现在可以运行测试了。安装了Resharper以后,在添加了TestClass特性的左侧,会看见两个重叠在一起的圆形图标。另外,在TestMethod特性左侧,有一个黑白相间的圆形图标。

  单击Test方法左侧的图标,然后点击Run按钮。如果单击TestClass特性左侧的图标,会运行该类所有测试。

  测试开始运行,并显示红色警告,提示未实现的异常,第一步完成。

  为了实现功能,现在来添加ToInt方法的代码。

  1. public static int ToInt( string s ) {
  2. int result;
  3. int.TryParse( s, out result );
  4. return result;
  5. }

  再次运行测试,已经能够成功通过,第二步完成。

  第三步是进行重构,现在看哪些地方可以重构。参数s看起来有点不爽,改成data,并添加XML注释。

  1. /// <summary>
  2. /// 转换为整型
  3. /// </summary>
  4. /// <param name="data">数据</param>
  5. public static int ToInt( string data ) {
  6. int result;
  7. int.TryParse( data, out result );
  8. return result;
  9. }

  另外重构一下测试,为了更容易找到相关测试,一般测试文件名使用类名+Test,现在测试文件名改成ConvTest.cs,测试类名改成ConvTest。把测试方法名改成TestToInt,并添加XML注释。

  1. /// <summary>
  2. /// 测试转换为整型
  3. /// </summary>
  4. [TestMethod]
  5. public void TestToInt() {
  6. Assert.AreEqual( , Util.Conv.ToInt( "" ) );
  7. }

  关于测试的命名,很多著作都提出了自己不同的方法。在《.Net单元测试艺术》中,作者建议使用三部分进行组合命名。还有一些著作建议将测试内容用下划线分隔单词,拼成一个长句子,以方便阅读和理解。这可能对英文水平好的人很有效,不过我的英文水平很烂,我拿一些单词拼成一个长句以后,发现更难理解了。所以我所采用的测试方法命名可能不一定好,你可以按你容易理解的方式来命名。

  重构之后,需要重新测试代码,以观察是否导致失败。

  上面简单介绍了TDD的一套开发流程,主要为了照顾还没有体验过单元测试的人,后面直接粘贴代码,以避免这样低效的叙述方式。

  单元测试代码如下。

  1. using System;
  2. using Microsoft.VisualStudio.TestTools.UnitTesting;
  3.  
  4. namespace Util.Tests {
  5. /// <summary>
  6. /// 类型转换公共操作类测试
  7. /// </summary>
  8. [TestClass]
  9. public class ConvTest {
  10.  
  11. #region ToInt(转换为整型)
  12.  
  13. /// <summary>
  14. ///转换为整型,值为null
  15. ///</summary>
  16. [TestMethod]
  17. public void TestToInt_Null() {
  18. Assert.AreEqual( , Util.Conv.ToInt( null ) );
  19. }
  20.  
  21. /// <summary>
  22. ///转换为整型,值为空字符串
  23. ///</summary>
  24. [TestMethod]
  25. public void TestToInt_Empty() {
  26. Assert.AreEqual( , Util.Conv.ToInt( "" ) );
  27. }
  28.  
  29. /// <summary>
  30. ///转换为整型,无效值
  31. ///</summary>
  32. [TestMethod]
  33. public void TestToInt_Invalid() {
  34. Assert.AreEqual( , Util.Conv.ToInt( "1A" ) );
  35. }
  36.  
  37. /// <summary>
  38. ///转换为整型,有效值
  39. ///</summary>
  40. [TestMethod]
  41. public void TestToInt() {
  42. Assert.AreEqual( , Util.Conv.ToInt( "" ) );
  43. Assert.AreEqual( , Util.Conv.ToInt( "1778019.7801684" ) );
  44. }
  45.  
  46. #endregion
  47.  
  48. #region ToIntOrNull(转换为可空整型)
  49.  
  50. /// <summary>
  51. ///转换为可空整型,值为null
  52. ///</summary>
  53. [TestMethod]
  54. public void TestToIntOrNull_Null() {
  55. Assert.IsNull( Util.Conv.ToIntOrNull( null ) );
  56. }
  57.  
  58. /// <summary>
  59. ///转换为可空整型,值为空字符串
  60. ///</summary>
  61. [TestMethod]
  62. public void TestToIntOrNull_Empty() {
  63. Assert.IsNull( Util.Conv.ToIntOrNull( "" ) );
  64. }
  65.  
  66. /// <summary>
  67. ///转换为可空整型,无效值
  68. ///</summary>
  69. [TestMethod]
  70. public void TestToIntOrNull_Invalid() {
  71. Assert.IsNull( Util.Conv.ToIntOrNull( "1A" ) );
  72. }
  73.  
  74. /// <summary>
  75. ///转换为可空整型,值为0
  76. ///</summary>
  77. [TestMethod]
  78. public void TestToIntOrNull_0() {
  79. Assert.AreEqual( , Util.Conv.ToIntOrNull( "" ) );
  80. }
  81.  
  82. /// <summary>
  83. ///转换为可空整型,有效值
  84. ///</summary>
  85. [TestMethod]
  86. public void TestToIntOrNull() {
  87. Assert.AreEqual( , Util.Conv.ToIntOrNull( "" ) );
  88. }
  89.  
  90. #endregion
  91.  
  92. #region ToDouble(转换为双精度浮点数)
  93.  
  94. /// <summary>
  95. ///转换为双精度浮点数,值为null
  96. ///</summary>
  97. [TestMethod]
  98. public void TestToDouble_Null() {
  99. Assert.AreEqual( , Util.Conv.ToDouble( null ) );
  100. }
  101.  
  102. /// <summary>
  103. ///转换为双精度浮点数,值为空字符串
  104. ///</summary>
  105. [TestMethod]
  106. public void TestToDouble_Empty() {
  107. Assert.AreEqual( , Util.Conv.ToDouble( "" ) );
  108. }
  109.  
  110. /// <summary>
  111. ///转换为双精度浮点数,无效值
  112. ///</summary>
  113. [TestMethod]
  114. public void TestToDouble_Invalid() {
  115. Assert.AreEqual( , Util.Conv.ToDouble( "1A" ) );
  116. }
  117.  
  118. /// <summary>
  119. ///转换为双精度浮点数,有效值
  120. ///</summary>
  121. [TestMethod]
  122. public void TestToDouble() {
  123. Assert.AreEqual( 1.2, Util.Conv.ToDouble( "1.2" ) );
  124. }
  125.  
  126. /// <summary>
  127. /// 转换为双精度浮点数,指定2位小数位数
  128. ///</summary>
  129. [TestMethod()]
  130. public void TestToDouble_DigitsIs2() {
  131. Assert.AreEqual( 12.36, Util.Conv.ToDouble( "12.355", ) );
  132. }
  133.  
  134. #endregion
  135.  
  136. #region ToDoubleOrNull(转换为可空双精度浮点数)
  137.  
  138. /// <summary>
  139. ///转换为可空双精度浮点数,值为null
  140. ///</summary>
  141. [TestMethod]
  142. public void TestToDoubleOrNull_Null() {
  143. Assert.IsNull( Util.Conv.ToDoubleOrNull( null ) );
  144. }
  145.  
  146. /// <summary>
  147. ///转换为可空双精度浮点数,值为空字符串
  148. ///</summary>
  149. [TestMethod]
  150. public void TestToDoubleOrNull_Empty() {
  151. Assert.IsNull( Util.Conv.ToDoubleOrNull( "" ) );
  152. }
  153.  
  154. /// <summary>
  155. ///转换为可空双精度浮点数,无效值
  156. ///</summary>
  157. [TestMethod]
  158. public void TestToDoubleOrNull_Invalid() {
  159. Assert.IsNull( Util.Conv.ToDoubleOrNull( "1A" ) );
  160. }
  161.  
  162. /// <summary>
  163. ///转换为可空双精度浮点数,值为0
  164. ///</summary>
  165. [TestMethod]
  166. public void TestToDoubleOrNull_0() {
  167. Assert.AreEqual( , Util.Conv.ToDoubleOrNull( "" ) );
  168. }
  169.  
  170. /// <summary>
  171. ///转换为可空双精度浮点数,有效值
  172. ///</summary>
  173. [TestMethod]
  174. public void TestToDoubleOrNull() {
  175. Assert.AreEqual( 1.2, Util.Conv.ToDoubleOrNull( "1.2" ) );
  176. }
  177.  
  178. #endregion
  179.  
  180. #region ToDecimal(转换为高精度浮点数)
  181.  
  182. /// <summary>
  183. ///转换为高精度浮点数,值为null
  184. ///</summary>
  185. [TestMethod]
  186. public void TestToDecimal_Null() {
  187. Assert.AreEqual( , Util.Conv.ToDecimal( null ) );
  188. }
  189.  
  190. /// <summary>
  191. ///转换为高精度浮点数,值为空字符串
  192. ///</summary>
  193. [TestMethod]
  194. public void TestToDecimal_Empty() {
  195. Assert.AreEqual( , Util.Conv.ToDecimal( "" ) );
  196. }
  197.  
  198. /// <summary>
  199. ///转换为高精度浮点数,无效值
  200. ///</summary>
  201. [TestMethod]
  202. public void TestToDecimal_Invalid() {
  203. Assert.AreEqual( , Util.Conv.ToDecimal( "1A" ) );
  204. }
  205.  
  206. /// <summary>
  207. ///转换为高精度浮点数,有效值
  208. ///</summary>
  209. [TestMethod]
  210. public void TestToDecimal() {
  211. Assert.AreEqual( 1.2M, Util.Conv.ToDecimal( "1.2" ) );
  212. }
  213.  
  214. /// <summary>
  215. /// 转换为高精度浮点数,指定2位小数位数
  216. ///</summary>
  217. [TestMethod()]
  218. public void TestToDecimal_DigitsIs2() {
  219. Assert.AreEqual( 12.24M, Util.Conv.ToDecimal( "12.235", ) );
  220. }
  221.  
  222. #endregion
  223.  
  224. #region ToDecimalOrNull(转换为可空高精度浮点数)
  225.  
  226. /// <summary>
  227. ///转换为可空高精度浮点数,值为null
  228. ///</summary>
  229. [TestMethod]
  230. public void TestToDecimalOrNull_Null() {
  231. Assert.IsNull( Util.Conv.ToDecimalOrNull( null ) );
  232. }
  233.  
  234. /// <summary>
  235. ///转换为可空高精度浮点数,值为空字符串
  236. ///</summary>
  237. [TestMethod]
  238. public void TestToDecimalOrNull_Empty() {
  239. Assert.IsNull( Util.Conv.ToDecimalOrNull( "" ) );
  240. }
  241.  
  242. /// <summary>
  243. ///转换为可空高精度浮点数,无效值
  244. ///</summary>
  245. [TestMethod]
  246. public void TestToDecimalOrNull_Invalid() {
  247. Assert.IsNull( Util.Conv.ToDecimalOrNull( "1A" ) );
  248. }
  249.  
  250. /// <summary>
  251. ///转换为可空高精度浮点数,无效值,指定2位小数位数
  252. ///</summary>
  253. [TestMethod]
  254. public void TestToDecimalOrNull_Invalid_DigitsIs2() {
  255. Assert.IsNull( Util.Conv.ToDecimalOrNull( "1A", ) );
  256. }
  257.  
  258. /// <summary>
  259. ///转换为可空高精度浮点数,值为0
  260. ///</summary>
  261. [TestMethod]
  262. public void TestToDecimalOrNull_0() {
  263. Assert.AreEqual( , Util.Conv.ToDecimalOrNull( "" ) );
  264. }
  265.  
  266. /// <summary>
  267. ///转换为可空高精度浮点数,有效值
  268. ///</summary>
  269. [TestMethod]
  270. public void TestToDecimalOrNull() {
  271. Assert.AreEqual( 1.2M, Util.Conv.ToDecimalOrNull( "1.2" ) );
  272. }
  273.  
  274. /// <summary>
  275. /// 转换为可空高精度浮点数,指定2位小数位数
  276. ///</summary>
  277. [TestMethod()]
  278. public void ToDecimalOrNull_DigitsIs2() {
  279. Assert.AreEqual( 12.24M, Util.Conv.ToDecimalOrNull( "12.235", ) );
  280. }
  281.  
  282. #endregion
  283.  
  284. #region ToGuid(转换为Guid)
  285.  
  286. /// <summary>
  287. ///转换为Guid,值为null
  288. ///</summary>
  289. [TestMethod]
  290. public void TestToGuid_Null() {
  291. Assert.AreEqual( Guid.Empty, Util.Conv.ToGuid( null ) );
  292. }
  293.  
  294. /// <summary>
  295. ///转换为Guid,值为空字符串
  296. ///</summary>
  297. [TestMethod]
  298. public void TestToGuid_Empty() {
  299. Assert.AreEqual( Guid.Empty, Util.Conv.ToGuid( "" ) );
  300. }
  301.  
  302. /// <summary>
  303. ///转换为Guid,无效值
  304. ///</summary>
  305. [TestMethod]
  306. public void TestToGuid_Invalid() {
  307. Assert.AreEqual( Guid.Empty, Util.Conv.ToGuid( "1A" ) );
  308. }
  309.  
  310. /// <summary>
  311. ///转换为Guid,有效值
  312. ///</summary>
  313. [TestMethod]
  314. public void TestToGuid() {
  315. Assert.AreEqual( new Guid( "B9EB56E9-B720-40B4-9425-00483D311DDC" ), Util.Conv.ToGuid( "B9EB56E9-B720-40B4-9425-00483D311DDC" ) );
  316. }
  317.  
  318. #endregion
  319.  
  320. #region ToGuidOrNull(转换为可空Guid)
  321.  
  322. /// <summary>
  323. ///转换为可空Guid,值为null
  324. ///</summary>
  325. [TestMethod]
  326. public void TestToGuidOrNull_Null() {
  327. Assert.IsNull( Util.Conv.ToGuidOrNull( null ) );
  328. }
  329.  
  330. /// <summary>
  331. ///转换为可空Guid,值为空字符串
  332. ///</summary>
  333. [TestMethod]
  334. public void TestToGuidOrNull_Empty() {
  335. Assert.IsNull( Util.Conv.ToGuidOrNull( "" ) );
  336. }
  337.  
  338. /// <summary>
  339. ///转换为可空Guid,无效值
  340. ///</summary>
  341. [TestMethod]
  342. public void TestToGuidOrNull_Invalid() {
  343. Assert.IsNull( Util.Conv.ToGuidOrNull( "1A" ) );
  344. }
  345.  
  346. /// <summary>
  347. ///转换为可空Guid,有效值
  348. ///</summary>
  349. [TestMethod]
  350. public void TestToGuidOrNull() {
  351. Assert.AreEqual( new Guid( "B9EB56E9-B720-40B4-9425-00483D311DDC" ), Util.Conv.ToGuidOrNull( "B9EB56E9-B720-40B4-9425-00483D311DDC" ) );
  352. }
  353.  
  354. #endregion
  355.  
  356. #region ToGuidList(转换为Guid集合)
  357.  
  358. /// <summary>
  359. /// 转换为Guid集合,验证空字符串
  360. /// </summary>
  361. [TestMethod]
  362. public void TestToGuidList_Empty() {
  363. Assert.AreEqual( , Util.Conv.ToGuidList( "" ).Count );
  364. }
  365.  
  366. /// <summary>
  367. /// 转换为Guid集合,验证最后为逗号
  368. /// </summary>
  369. [TestMethod]
  370. public void TestToGuidList_LastIsComma() {
  371. Assert.AreEqual( , Util.Conv.ToGuidList( "83B0233C-A24F-49FD-8083-1337209EBC9A," ).Count );
  372. }
  373.  
  374. /// <summary>
  375. /// 转换为Guid集合,验证中间包含逗号
  376. /// </summary>
  377. [TestMethod]
  378. public void TestToGuidList_MiddleIsComma() {
  379. const string guid = "83B0233C-A24F-49FD-8083-1337209EBC9A,,EAB523C6-2FE7-47BE-89D5-C6D440C3033A,";
  380. Assert.AreEqual( , Util.Conv.ToGuidList( guid ).Count );
  381. Assert.AreEqual( new Guid( "83B0233C-A24F-49FD-8083-1337209EBC9A" ), Util.Conv.ToGuidList( guid )[] );
  382. Assert.AreEqual( new Guid( "EAB523C6-2FE7-47BE-89D5-C6D440C3033A" ), Util.Conv.ToGuidList( guid )[] );
  383. }
  384.  
  385. /// <summary>
  386. /// 转换为Guid集合,仅1个Guid
  387. /// </summary>
  388. [TestMethod]
  389. public void TestToGuidList_1Guid() {
  390. const string guid = "83B0233C-A24F-49FD-8083-1337209EBC9A";
  391. Assert.AreEqual( , Util.Conv.ToGuidList( guid ).Count );
  392. Assert.AreEqual( new Guid( guid ), Util.Conv.ToGuidList( guid )[] );
  393. }
  394.  
  395. /// <summary>
  396. /// 转换为Guid集合,2个Guid
  397. /// </summary>
  398. [TestMethod]
  399. public void TestToGuidList_2Guid() {
  400. const string guid = "83B0233C-A24F-49FD-8083-1337209EBC9A,EAB523C6-2FE7-47BE-89D5-C6D440C3033A";
  401. Assert.AreEqual( , Util.Conv.ToGuidList( guid ).Count );
  402. Assert.AreEqual( new Guid( "83B0233C-A24F-49FD-8083-1337209EBC9A" ), Util.Conv.ToGuidList( guid )[] );
  403. Assert.AreEqual( new Guid( "EAB523C6-2FE7-47BE-89D5-C6D440C3033A" ), Util.Conv.ToGuidList( guid )[] );
  404. }
  405.  
  406. #endregion
  407.  
  408. #region ToDate(转换为日期)
  409.  
  410. /// <summary>
  411. ///转换为日期,值为null
  412. ///</summary>
  413. [TestMethod]
  414. public void TestToDate_Null() {
  415. Assert.AreEqual( DateTime.MinValue, Util.Conv.ToDate( null ) );
  416. }
  417.  
  418. /// <summary>
  419. ///转换为日期,值为空字符串
  420. ///</summary>
  421. [TestMethod]
  422. public void TestToDate_Empty() {
  423. Assert.AreEqual( DateTime.MinValue, Util.Conv.ToDate( "" ) );
  424. }
  425.  
  426. /// <summary>
  427. ///转换为日期,无效值
  428. ///</summary>
  429. [TestMethod]
  430. public void TestToDate_Invalid() {
  431. Assert.AreEqual( DateTime.MinValue, Util.Conv.ToDate( "1A" ) );
  432. }
  433.  
  434. /// <summary>
  435. ///转换为日期,有效值
  436. ///</summary>
  437. [TestMethod]
  438. public void TestToDate() {
  439. Assert.AreEqual( new DateTime( , , ), Util.Conv.ToDate( "2000-1-1" ) );
  440. }
  441.  
  442. #endregion
  443.  
  444. #region ToDateOrNull(转换为可空日期)
  445.  
  446. /// <summary>
  447. ///转换为可空日期,值为null
  448. ///</summary>
  449. [TestMethod]
  450. public void TestToDateOrNull_Null() {
  451. Assert.IsNull( Util.Conv.ToDateOrNull( null ) );
  452. }
  453.  
  454. /// <summary>
  455. ///转换为可空日期,值为空字符串
  456. ///</summary>
  457. [TestMethod]
  458. public void TestToDateOrNull_Empty() {
  459. Assert.IsNull( Util.Conv.ToDateOrNull( "" ) );
  460. }
  461.  
  462. /// <summary>
  463. ///转换为可空日期,无效值
  464. ///</summary>
  465. [TestMethod]
  466. public void TestToDateOrNull_Invalid() {
  467. Assert.IsNull( Util.Conv.ToDateOrNull( "1A" ) );
  468. }
  469.  
  470. /// <summary>
  471. ///转换为可空日期,有效值
  472. ///</summary>
  473. [TestMethod]
  474. public void TestToDateOrNull() {
  475. Assert.AreEqual( new DateTime( , , ), Util.Conv.ToDateOrNull( "2000-1-1" ) );
  476. }
  477.  
  478. #endregion
  479.  
  480. #region ToBool(转换为布尔值)
  481.  
  482. /// <summary>
  483. ///转换为布尔值,值为null
  484. ///</summary>
  485. [TestMethod]
  486. public void TestToBool_Null() {
  487. Assert.AreEqual( false, Util.Conv.ToBool( null ) );
  488. }
  489.  
  490. /// <summary>
  491. ///转换为布尔值,值为空字符串
  492. ///</summary>
  493. [TestMethod]
  494. public void TestToBool_Empty() {
  495. Assert.AreEqual( false, Util.Conv.ToBool( "" ) );
  496. }
  497.  
  498. /// <summary>
  499. ///转换为布尔值,无效值
  500. ///</summary>
  501. [TestMethod]
  502. public void TestToBool_Invalid() {
  503. Assert.AreEqual( false, Util.Conv.ToBool( "1A" ) );
  504. }
  505.  
  506. /// <summary>
  507. ///转换为布尔值,值为False
  508. ///</summary>
  509. [TestMethod]
  510. public void TestToBool_False() {
  511. Assert.AreEqual( false, Util.Conv.ToBool( "" ) );
  512. Assert.AreEqual( false, Util.Conv.ToBool( "否" ) );
  513. Assert.AreEqual( false, Util.Conv.ToBool( "no" ) );
  514. Assert.AreEqual( false, Util.Conv.ToBool( "No" ) );
  515. Assert.AreEqual( false, Util.Conv.ToBool( "false" ) );
  516. Assert.AreEqual( false, Util.Conv.ToBool( "False" ) );
  517. }
  518.  
  519. /// <summary>
  520. ///转换为布尔值,值为True
  521. ///</summary>
  522. [TestMethod]
  523. public void TestToBool_True() {
  524. Assert.AreEqual( true, Util.Conv.ToBool( "" ) );
  525. Assert.AreEqual( true, Util.Conv.ToBool( "是" ) );
  526. Assert.AreEqual( true, Util.Conv.ToBool( "yes" ) );
  527. Assert.AreEqual( true, Util.Conv.ToBool( "Yes" ) );
  528. Assert.AreEqual( true, Util.Conv.ToBool( "true" ) );
  529. Assert.AreEqual( true, Util.Conv.ToBool( "True" ) );
  530. }
  531.  
  532. #endregion
  533.  
  534. #region ToBoolOrNull(转换为可空布尔值)
  535.  
  536. /// <summary>
  537. ///转换为可空布尔值,值为null
  538. ///</summary>
  539. [TestMethod]
  540. public void TestToBoolOrNull_Null() {
  541. Assert.IsNull( Util.Conv.ToBoolOrNull( null ) );
  542. }
  543.  
  544. /// <summary>
  545. ///转换为可空布尔值,值为空字符串
  546. ///</summary>
  547. [TestMethod]
  548. public void TestToBoolOrNull_Empty() {
  549. Assert.IsNull( Util.Conv.ToBoolOrNull( "" ) );
  550. }
  551.  
  552. /// <summary>
  553. ///转换为可空布尔值,无效值
  554. ///</summary>
  555. [TestMethod]
  556. public void TestToBoolOrNull_Invalid() {
  557. Assert.IsNull( Util.Conv.ToBoolOrNull( "1A" ) );
  558. }
  559.  
  560. /// <summary>
  561. ///转换为布尔值,值为False
  562. ///</summary>
  563. [TestMethod]
  564. public void TestToBoolOrNull_False() {
  565. Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "" ) );
  566. Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "否" ) );
  567. Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "no" ) );
  568. Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "No" ) );
  569. Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "false" ) );
  570. Assert.AreEqual( false, Util.Conv.ToBoolOrNull( "False" ) );
  571. }
  572.  
  573. /// <summary>
  574. ///转换为布尔值,值为True
  575. ///</summary>
  576. [TestMethod]
  577. public void TestToBoolOrNull_True() {
  578. Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "" ) );
  579. Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "是" ) );
  580. Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "yes" ) );
  581. Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "Yes" ) );
  582. Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "true" ) );
  583. Assert.AreEqual( true, Util.Conv.ToBoolOrNull( "True" ) );
  584. }
  585.  
  586. #endregion
  587.  
  588. #region ToString(转换为字符串)
  589.  
  590. /// <summary>
  591. ///转换为字符串,值为null
  592. ///</summary>
  593. [TestMethod]
  594. public void TestToString_Null() {
  595. Assert.AreEqual( string.Empty, Util.Conv.ToString( null ) );
  596. }
  597.  
  598. /// <summary>
  599. ///转换为字符串,值为空字符串
  600. ///</summary>
  601. [TestMethod]
  602. public void TestToString_Empty() {
  603. Assert.AreEqual( string.Empty, Util.Conv.ToString( " " ) );
  604. }
  605.  
  606. /// <summary>
  607. ///转换为字符串,有效值
  608. ///</summary>
  609. [TestMethod]
  610. public void TestToString() {
  611. Assert.AreEqual( "", Util.Conv.ToString( ) );
  612. }
  613.  
  614. #endregion
  615.  
  616. #region To(通用泛型转换)
  617.  
  618. #region 目标为int
  619.  
  620. /// <summary>
  621. ///通用泛型转换,目标为整数,值为null
  622. ///</summary>
  623. [TestMethod]
  624. public void TestTo_Int_Null() {
  625. Assert.AreEqual( , Conv.To<int>( null ) );
  626. }
  627.  
  628. /// <summary>
  629. ///通用泛型转换,目标为整数,值为空字符串
  630. ///</summary>
  631. [TestMethod]
  632. public void TestTo_Int_Empty() {
  633. Assert.AreEqual( , Conv.To<int>( "" ) );
  634. }
  635.  
  636. /// <summary>
  637. ///通用泛型转换,目标为整数,无效值
  638. ///</summary>
  639. [TestMethod]
  640. public void TestTo_Int_Invalid() {
  641. Assert.AreEqual( , Conv.To<int>( "1A" ) );
  642. }
  643.  
  644. /// <summary>
  645. ///通用泛型转换,目标为整数,有效值
  646. ///</summary>
  647. [TestMethod]
  648. public void TestTo_Int() {
  649. Assert.AreEqual( , Conv.To<int>( "" ) );
  650. }
  651.  
  652. /// <summary>
  653. ///通用泛型转换,目标为可空整数,无效值
  654. ///</summary>
  655. [TestMethod]
  656. public void TestTo_IntOrNull_Invalid() {
  657. Assert.IsNull( Conv.To<int?>( "1A" ) );
  658. }
  659.  
  660. /// <summary>
  661. ///通用泛型转换,目标为可空整数,有效值
  662. ///</summary>
  663. [TestMethod]
  664. public void TestTo_IntOrNull() {
  665. Assert.AreEqual( , Conv.To<int?>( "" ) );
  666. }
  667.  
  668. #endregion
  669.  
  670. #region 目标为Guid
  671.  
  672. /// <summary>
  673. ///通用泛型转换,目标为Guid,无效值
  674. ///</summary>
  675. [TestMethod]
  676. public void TestTo_Guid_Invalid() {
  677. Assert.AreEqual( Guid.Empty, Conv.To<Guid>( "1A" ) );
  678. }
  679.  
  680. /// <summary>
  681. ///通用泛型转换,目标为Guid,有效值
  682. ///</summary>
  683. [TestMethod]
  684. public void TestTo_Guid() {
  685. Assert.AreEqual( new Guid( "B9EB56E9-B720-40B4-9425-00483D311DDC" ),
  686. Conv.To<Guid>( "B9EB56E9-B720-40B4-9425-00483D311DDC" ) );
  687. }
  688.  
  689. /// <summary>
  690. ///通用泛型转换,目标为可空Guid,无效值
  691. ///</summary>
  692. [TestMethod]
  693. public void TestTo_GuidOrNull_Invalid() {
  694. Assert.IsNull( Conv.To<Guid?>( "1A" ) );
  695. }
  696.  
  697. /// <summary>
  698. ///通用泛型转换,目标为可空Guid,有效值
  699. ///</summary>
  700. [TestMethod]
  701. public void TestTo_GuidOrNull() {
  702. Assert.AreEqual( new Guid( "B9EB56E9-B720-40B4-9425-00483D311DDC" ),
  703. Conv.To<Guid?>( "B9EB56E9-B720-40B4-9425-00483D311DDC" ) );
  704. }
  705.  
  706. #endregion
  707.  
  708. #region 目标为string
  709.  
  710. /// <summary>
  711. ///通用泛型转换,目标为string,有效值
  712. ///</summary>
  713. [TestMethod]
  714. public void TestTo_String() {
  715. Assert.AreEqual( "", Conv.To<string>( ) );
  716. }
  717.  
  718. #endregion
  719.  
  720. #region 目标为double
  721.  
  722. /// <summary>
  723. ///通用泛型转换,目标为double,无效值
  724. ///</summary>
  725. [TestMethod]
  726. public void TestTo_Double_Invalid() {
  727. Assert.AreEqual( , Conv.To<double>( "1A" ) );
  728. }
  729.  
  730. /// <summary>
  731. ///通用泛型转换,目标为double,有效值
  732. ///</summary>
  733. [TestMethod]
  734. public void TestTo_Double() {
  735. Assert.AreEqual( 12.5, Conv.To<double>( "12.5" ) );
  736. }
  737.  
  738. /// <summary>
  739. ///通用泛型转换,目标为可空double,无效值
  740. ///</summary>
  741. [TestMethod]
  742. public void TestTo_DoubleOrNull_Invalid() {
  743. Assert.IsNull( Conv.To<double?>( "1A" ) );
  744. }
  745.  
  746. /// <summary>
  747. ///通用泛型转换,目标为可空double,有效值
  748. ///</summary>
  749. [TestMethod]
  750. public void TestTo_DoubleOrNull() {
  751. Assert.AreEqual( 12.5, Conv.To<double?>( "12.5" ) );
  752. }
  753.  
  754. #endregion
  755.  
  756. #region 目标为decimal
  757.  
  758. /// <summary>
  759. ///通用泛型转换,目标为decimal,无效值
  760. ///</summary>
  761. [TestMethod]
  762. public void TestTo_Decimal_Invalid() {
  763. Assert.AreEqual( , Conv.To<decimal>( "1A" ) );
  764. }
  765.  
  766. /// <summary>
  767. ///通用泛型转换,目标为decimal,有效值
  768. ///</summary>
  769. [TestMethod]
  770. public void TestTo_Decimal() {
  771. Assert.AreEqual( 12.5M, Conv.To<decimal>( "12.5" ) );
  772. }
  773.  
  774. /// <summary>
  775. ///通用泛型转换,目标为可空decimal,无效值
  776. ///</summary>
  777. [TestMethod]
  778. public void TestTo_DecimalOrNull_Invalid() {
  779. Assert.IsNull( Conv.To<decimal?>( "1A" ) );
  780. }
  781.  
  782. /// <summary>
  783. ///通用泛型转换,目标为可空decimal,有效值
  784. ///</summary>
  785. [TestMethod]
  786. public void TestTo_DecimalOrNull() {
  787. Assert.AreEqual( 12.5M, Conv.To<decimal?>( "12.5" ) );
  788. }
  789.  
  790. #endregion
  791.  
  792. #region 目标为bool
  793.  
  794. /// <summary>
  795. ///通用泛型转换,目标为bool,无效值
  796. ///</summary>
  797. [TestMethod]
  798. public void TestTo_Bool_Invalid() {
  799. Assert.AreEqual( false, Conv.To<bool>( "1A" ) );
  800. }
  801.  
  802. /// <summary>
  803. ///通用泛型转换,目标为bool,有效值
  804. ///</summary>
  805. [TestMethod]
  806. public void TestTo_Bool() {
  807. Assert.AreEqual( true, Conv.To<bool>( ) );
  808. }
  809.  
  810. /// <summary>
  811. ///通用泛型转换,目标为可空bool,无效值
  812. ///</summary>
  813. [TestMethod]
  814. public void TestTo_BoolOrNull_Invalid() {
  815. Assert.IsNull( Conv.To<bool?>( "1A" ) );
  816. }
  817.  
  818. /// <summary>
  819. ///通用泛型转换,目标为可空bool,有效值
  820. ///</summary>
  821. [TestMethod]
  822. public void TestTo_BoolOrNull() {
  823. Assert.AreEqual( true, Conv.To<bool?>( "true" ) );
  824. }
  825.  
  826. #endregion
  827.  
  828. #region 目标为DateTime
  829.  
  830. /// <summary>
  831. ///通用泛型转换,目标为DateTime,无效值
  832. ///</summary>
  833. [TestMethod]
  834. public void TestTo_DateTime_Invalid() {
  835. Assert.AreEqual( DateTime.MinValue, Conv.To<DateTime>( "1A" ) );
  836. }
  837.  
  838. /// <summary>
  839. ///通用泛型转换,目标为DateTime,有效值
  840. ///</summary>
  841. [TestMethod]
  842. public void TestTo_DateTime() {
  843. Assert.AreEqual( new DateTime( , , ), Conv.To<DateTime>( "2000-1-1" ) );
  844. }
  845.  
  846. /// <summary>
  847. ///通用泛型转换,目标为可空DateTime,无效值
  848. ///</summary>
  849. [TestMethod]
  850. public void TestTo_DateTimeOrNull_Invalid() {
  851. Assert.IsNull( Conv.To<DateTime?>( "1A" ) );
  852. }
  853.  
  854. /// <summary>
  855. ///通用泛型转换,目标为可空DateTime,有效值
  856. ///</summary>
  857. [TestMethod]
  858. public void TestTo_DateTimeOrNull() {
  859. Assert.AreEqual( new DateTime( , , ), Conv.To<DateTime?>( "2000-1-1" ) );
  860. }
  861.  
  862. #endregion
  863.  
  864. #endregion
  865. }
  866. }

ConvTest

  Conv类代码如下。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. namespace Util {
  6. /// <summary>
  7. /// 类型转换
  8. /// </summary>
  9. public static class Conv {
  10.  
  11. #region 数值转换
  12.  
  13. /// <summary>
  14. /// 转换为整型
  15. /// </summary>
  16. /// <param name="data">数据</param>
  17. public static int ToInt( object data ) {
  18. if ( data == null )
  19. return ;
  20. int result;
  21. var success = int.TryParse( data.ToString(), out result );
  22. if ( success == true )
  23. return result;
  24. try {
  25. return Convert.ToInt32( ToDouble( data, ) );
  26. }
  27. catch ( Exception ) {
  28. return ;
  29. }
  30. }
  31.  
  32. /// <summary>
  33. /// 转换为可空整型
  34. /// </summary>
  35. /// <param name="data">数据</param>
  36. public static int? ToIntOrNull( object data ) {
  37. if ( data == null )
  38. return null;
  39. int result;
  40. bool isValid = int.TryParse( data.ToString(), out result );
  41. if ( isValid )
  42. return result;
  43. return null;
  44. }
  45.  
  46. /// <summary>
  47. /// 转换为双精度浮点数
  48. /// </summary>
  49. /// <param name="data">数据</param>
  50. public static double ToDouble( object data ) {
  51. if ( data == null )
  52. return ;
  53. double result;
  54. return double.TryParse( data.ToString(), out result ) ? result : ;
  55. }
  56.  
  57. /// <summary>
  58. /// 转换为双精度浮点数,并按指定的小数位4舍5入
  59. /// </summary>
  60. /// <param name="data">数据</param>
  61. /// <param name="digits">小数位数</param>
  62. public static double ToDouble( object data, int digits ) {
  63. return Math.Round( ToDouble( data ), digits );
  64. }
  65.  
  66. /// <summary>
  67. /// 转换为可空双精度浮点数
  68. /// </summary>
  69. /// <param name="data">数据</param>
  70. public static double? ToDoubleOrNull( object data ) {
  71. if ( data == null )
  72. return null;
  73. double result;
  74. bool isValid = double.TryParse( data.ToString(), out result );
  75. if ( isValid )
  76. return result;
  77. return null;
  78. }
  79.  
  80. /// <summary>
  81. /// 转换为高精度浮点数
  82. /// </summary>
  83. /// <param name="data">数据</param>
  84. public static decimal ToDecimal( object data ) {
  85. if ( data == null )
  86. return ;
  87. decimal result;
  88. return decimal.TryParse( data.ToString(), out result ) ? result : ;
  89. }
  90.  
  91. /// <summary>
  92. /// 转换为高精度浮点数,并按指定的小数位4舍5入
  93. /// </summary>
  94. /// <param name="data">数据</param>
  95. /// <param name="digits">小数位数</param>
  96. public static decimal ToDecimal( object data, int digits ) {
  97. return Math.Round( ToDecimal( data ), digits );
  98. }
  99.  
  100. /// <summary>
  101. /// 转换为可空高精度浮点数
  102. /// </summary>
  103. /// <param name="data">数据</param>
  104. public static decimal? ToDecimalOrNull( object data ) {
  105. if ( data == null )
  106. return null;
  107. decimal result;
  108. bool isValid = decimal.TryParse( data.ToString(), out result );
  109. if ( isValid )
  110. return result;
  111. return null;
  112. }
  113.  
  114. /// <summary>
  115. /// 转换为可空高精度浮点数,并按指定的小数位4舍5入
  116. /// </summary>
  117. /// <param name="data">数据</param>
  118. /// <param name="digits">小数位数</param>
  119. public static decimal? ToDecimalOrNull( object data, int digits ) {
  120. var result = ToDecimalOrNull( data );
  121. if ( result == null )
  122. return null;
  123. return Math.Round( result.Value, digits );
  124. }
  125.  
  126. #endregion
  127.  
  128. #region Guid转换
  129.  
  130. /// <summary>
  131. /// 转换为Guid
  132. /// </summary>
  133. /// <param name="data">数据</param>
  134. public static Guid ToGuid( object data ) {
  135. if ( data == null )
  136. return Guid.Empty;
  137. Guid result;
  138. return Guid.TryParse( data.ToString(), out result ) ? result : Guid.Empty;
  139. }
  140.  
  141. /// <summary>
  142. /// 转换为可空Guid
  143. /// </summary>
  144. /// <param name="data">数据</param>
  145. public static Guid? ToGuidOrNull( object data ) {
  146. if ( data == null )
  147. return null;
  148. Guid result;
  149. bool isValid = Guid.TryParse( data.ToString(), out result );
  150. if ( isValid )
  151. return result;
  152. return null;
  153. }
  154.  
  155. /// <summary>
  156. /// 转换为Guid集合
  157. /// </summary>
  158. /// <param name="guid">guid集合字符串,范例:83B0233C-A24F-49FD-8083-1337209EBC9A,EAB523C6-2FE7-47BE-89D5-C6D440C3033A</param>
  159. public static List<Guid> ToGuidList( string guid ) {
  160. var listGuid = new List<Guid>();
  161. if ( string.IsNullOrWhiteSpace( guid ) )
  162. return listGuid;
  163. var arrayGuid = guid.Split( ',' );
  164. listGuid.AddRange( from each in arrayGuid where !string.IsNullOrWhiteSpace( each ) select new Guid( each ) );
  165. return listGuid;
  166. }
  167.  
  168. #endregion
  169.  
  170. #region 日期转换
  171.  
  172. /// <summary>
  173. /// 转换为日期
  174. /// </summary>
  175. /// <param name="data">数据</param>
  176. public static DateTime ToDate( object data ) {
  177. if ( data == null )
  178. return DateTime.MinValue;
  179. DateTime result;
  180. return DateTime.TryParse( data.ToString(), out result ) ? result : DateTime.MinValue;
  181. }
  182.  
  183. /// <summary>
  184. /// 转换为可空日期
  185. /// </summary>
  186. /// <param name="data">数据</param>
  187. public static DateTime? ToDateOrNull( object data ) {
  188. if ( data == null )
  189. return null;
  190. DateTime result;
  191. bool isValid = DateTime.TryParse( data.ToString(), out result );
  192. if ( isValid )
  193. return result;
  194. return null;
  195. }
  196.  
  197. #endregion
  198.  
  199. #region 布尔转换
  200.  
  201. /// <summary>
  202. /// 转换为布尔值
  203. /// </summary>
  204. /// <param name="data">数据</param>
  205. public static bool ToBool( object data ) {
  206. if ( data == null )
  207. return false;
  208. bool? value = GetBool( data );
  209. if ( value != null )
  210. return value.Value;
  211. bool result;
  212. return bool.TryParse( data.ToString(), out result ) && result;
  213. }
  214.  
  215. /// <summary>
  216. /// 获取布尔值
  217. /// </summary>
  218. private static bool? GetBool( object data ) {
  219. switch ( data.ToString().Trim().ToLower() ) {
  220. case "":
  221. return false;
  222. case "":
  223. return true;
  224. case "是":
  225. return true;
  226. case "否":
  227. return false;
  228. case "yes":
  229. return true;
  230. case "no":
  231. return false;
  232. default:
  233. return null;
  234. }
  235. }
  236.  
  237. /// <summary>
  238. /// 转换为可空布尔值
  239. /// </summary>
  240. /// <param name="data">数据</param>
  241. public static bool? ToBoolOrNull( object data ) {
  242. if ( data == null )
  243. return null;
  244. bool? value = GetBool( data );
  245. if ( value != null )
  246. return value.Value;
  247. bool result;
  248. bool isValid = bool.TryParse( data.ToString(), out result );
  249. if ( isValid )
  250. return result;
  251. return null;
  252. }
  253.  
  254. #endregion
  255.  
  256. #region 字符串转换
  257.  
  258. /// <summary>
  259. /// 转换为字符串
  260. /// </summary>
  261. /// <param name="data">数据</param>
  262. public static string ToString( object data ) {
  263. return data == null ? string.Empty : data.ToString().Trim();
  264. }
  265.  
  266. #endregion
  267.  
  268. #region 通用转换
  269.  
  270. /// <summary>
  271. /// 泛型转换
  272. /// </summary>
  273. /// <typeparam name="T">目标类型</typeparam>
  274. /// <param name="data">数据</param>
  275. public static T To<T>( object data ) {
  276. if ( data == null || string.IsNullOrWhiteSpace( data.ToString() ) )
  277. return default( T );
  278. Type type = Nullable.GetUnderlyingType( typeof( T ) ) ?? typeof( T );
  279. try {
  280. if ( type.Name.ToLower() == "guid" )
  281. return (T)(object)new Guid( data.ToString() );
  282. if ( data is IConvertible )
  283. return (T)Convert.ChangeType( data, type );
  284. return (T)data;
  285. }
  286. catch {
  287. return default( T );
  288. }
  289. }
  290.  
  291. #endregion
  292. }
  293. }

Conv

  Conv公共操作类的用法,在单元测试中已经说得很清楚了,这也是单元测试的一个用途,即作为API说明文档。

  单元测试最强大的地方,可能是能够帮助你回归测试,如果你发现我的代码有BUG,请通知我一声,我只需要在单元测试中增加一个测试来捕获这个BUG,就可以永久修复它,并且由于采用TDD方式可以获得很高的测试覆盖率,所以我花上几秒钟运行一下全部测试,就可以知道这次修改有没有影响其它代码。这也是你创建自己的应用程序框架所必须要做的,它可以给你提供信心。

  可以看到,我在单元测试中进行了很多边界测试,比如参数为null或空字符串等。但不可能穷举所有可能出错的情况,因为可能想不到,另外时间有限,也不可能做到。当在项目上发现BUG后,再通过添加单元测试的方式修复BUG就可以了。由于你的项目代码调用的是应用程序框架API,所以你只需要在框架内修复一次,项目代码完全不动。

  像数据类型转换这样简单的操作,你发现写单元测试非常容易,因为它有明确的返回值,但如果没有返回值呢,甚至有外部依赖呢,那就没有这么简单了,需要很多技巧,所以你多看几本TDD和单元测试方面的著作有很多好处。

  另外,再补充一下,Conv这个类里面有几个法宝。一个是ToGuidList这个方法,当你需要把字符串转换为List<Guid>的时候就用它。还有一个泛型转换的方法To<T>,很多时候可以用它进行泛型转换。

  最后,我把所有方法参数类型都改成了object,主要是想使用起来方便一点,而不是只支持字符串参数,这可能导致装箱和拆箱,从而造成一些性能损失,不过我的大多数项目在性能方面还没有这么高的要求,所以这个损失对我来讲无关痛痒。

  还有些数据类型转换,我没有放进来,主要是我平时很少用到,当我用到时再增加。

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

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

  下载地址: http://files.cnblogs.com/xiadao521/Util.2014.11.12.1.rar

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

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

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

  2. 深入浅出Mybatis系列(二)---配置简介(mybatis源码篇)

    上篇文章<深入浅出Mybatis系列(一)---Mybatis入门>, 写了一个Demo简单体现了一下Mybatis的流程.本次,将简单介绍一下Mybatis的配置文件: 上次例子中,我们 ...

  3. 深入浅出Mybatis系列(二)---配置简介(mybatis源码篇)[转]

    上篇文章<深入浅出Mybatis系列(一)---Mybatis入门>, 写了一个Demo简单体现了一下Mybatis的流程.本次,将简单介绍一下Mybatis的配置文件: 上次例子中,我们 ...

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

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

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

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

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

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

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

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

  8. Util应用程序框架公共操作类(一):数据类型转换公共操作类(介绍篇)

    本系列文章将介绍一些对初学者有帮助的辅助类,这些辅助类本身并没有什么稀奇之处,如何能发现需要封装它们可能更加重要,所谓授之以鱼不如授之以渔,掌握封装公共操作类的技巧才是关键,我会详细说明创建这些类的动 ...

  9. 应用程序框架实战十五:DDD分层架构之领域实体(验证篇)

    在应用程序框架实战十四:DDD分层架构之领域实体(基础篇)一文中,我介绍了领域实体的基础,包括标识.相等性比较.输出实体状态等.本文将介绍领域实体的一个核心内容——验证,它是应用程序健壮性的基石.为了 ...

随机推荐

  1. js基础3

    内置对象 内置对象就是JS提供的一套工具箱,我们通过内置可以很方便的进行一些操作. Math对象: Math.ceil() //向上取整,天花板 Math.floor() //向下取整,地板 Math ...

  2. bootstrap之HTML模板

    bootstrap之HTML模板 <!DOCTYPE html> <html> <head> <title>Bootstrap 模板</title ...

  3. int.Parse()之异常

    首先对不起各位读者,我必须发泄一下,为了清明节能顺利的去洛阳玩,我周四赶出了一篇博客,就在快写完提交的时刻,11:30分断网了!!断网了!!断!!网!!了!!是的,你没有听错,他就这样毫无征兆的断网了 ...

  4. sql server 代理服务

    sql server 创建维护计划失败.错误代码:c001f011. 从 IClassFactory 为 CLSID 为 {17BCA6E8-A95D-497E-B2F9-AF6AA475916F} ...

  5. *HDU3398 数学

    String Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  6. eclipse maven java1.8支持

    下载Java 8并确保你的Eclipse版本是Kepler SR2. 选择菜单:"Help > Eclipse Marketplace-". 在搜索框中输入"Jav ...

  7. 系统定位在iOS8中的改变

    CLLocationManager这个系统定位的类在iOS8之前要实现定位,只需要遵守CLLocationManagerDelegate这个代理即可: - (void)startLocate {   ...

  8. js 模版加载到前端

    js 模版加载到前端 简单有效不高端 配个路由 /js/:filename ,  用 readTemplate 响应请求,前端可以按模块方式直接 require 模板 'use strict' var ...

  9. 非常棒的Android对话框效果

    FlycoDialog_Master http://www.see-source.com/androidwidget/detail.html?wid=488 带有各种动画效果的弹出对话框控件.你也可以 ...

  10. Call for Papers IEEE/ACM International Conference on Advances in Social Network Analysis and Mining (ASONAM)

    IEEE/ACM International Conference on Advances in Social Network Analysis and Mining (ASONAM) 2014 In ...