项目架构开发:展现层(下)
上一章我们完成了项目的展现层的一个表的CURD,从此UI层到数据库的通道打通了;传送门:项目架构开发:展现层(上)
这章我们还是讲CURD,不过内容重复的话就没意思了,这次我们想办法提高代码编写的效率;
先来看看从UI层到DataAccess一共要写多少个类文件,服务层就先不算在里边了
1、DataAccess Layer
这部分是一次性的工作,完成后之后几乎不用修改,所以这个关系不大
2、Business Logic Layer
业务逻辑层有8个类需要写,以LoginUser举例
分别是:
1. LoginUser.cs
2. ILoginUserRepository.cs
3. LoginUserRepository.cs
4. LoginUserApplication.cs
5. ILoginUserApplication.cs
6. LoginUserRequest.cs
7. LoginUserResponse.cs
8. LoginUserApplicationTest.cs
3、展现层
9. LoginUserController.cs
10. LoginUserViewModel.cs
11. LoginUser/Index.cshtml
12. LoginUserControllerTest.cs
好了,一共12个,如果view及JS分多文件的话可能得有15个左右,要是服务层再加进来,恐怕得有18个左右
这不得不说多层架构也实在是够麻烦的,单单一个表结构的CURD就要写那么多的类,要是有几百个表,那工作量简直不敢想象;汗。。
相反要是普通的三层可能只有5个左右,而实际上按照学校里的教科书那样,一个不写也是可以完成的,直接在aspx.cs里边一个方法搞定;
但是既然选择了多层开发,这种情况肯定得有后续手段能解决掉; 我能想到的就是代码生成器了,这就是本章的主题
代码生成器有很多,比较有名的比如李天平的“动软”,记得刚入行的时候看到“动软”,崇拜的不行,好像现在还在维护的;
但是就是觉得动软的模板配置不灵活,太重了;后来自己搞了一个比较简单的代码生成器,传送门:代码生成器
具体就不介绍了,这次主要是演示一些结合代码生成器批量生产代码的威力;
因为在上一章我们已经有了上边12个类的已经运行成功的代码。所以我们就以这12个文件为模板,批量生成其他表的所有类
连测试类也不放过,因为生成后要单元测试的。
我们开始吧!
4、新增模板文件
应用逻辑类:{0}Application.cs
1 using Business.DTO.Request; 2 using Business.DTO.Response; 3 using Business.ReverseDDD.IRepository; 4 using Business.ReverseDDD.Model; 5 using Business.ReverseDDD.Repository; 6 using Infrastructure.Common; 7 using Infrastructure.Data.UnitOfWork; 8 using Infrastructure.Interface; 9 using System; 10 using System.Collections.Generic; 11 using System.Linq; 12 using System.Linq.Expressions; 13 using Business.ReverseDDD.IApplication; 14 15 namespace Business.ReverseDDD.Application 16 { 17 public class ${ClassName}Application : I${ClassName}Application 18 { 19 private IUnitOfWork<${ClassName}> unitOfWork; 20 private I${ClassName}Repository repository; 21 22 public ${ClassName}Application() 23 { 24 this.unitOfWork = new UnitOfWork<${ClassName}>(); 25 this.repository = new ${ClassName}Repository(this.unitOfWork); 26 } 27 28 public bool Add(${ClassName}CURequest entity) 29 { 30 this.repository.Add(new ${ClassName}() 31 { 32 #foreach($Column in $ColumnList) 33 #if(${Column.StandardText}!="CreateTime") 34 ${Column.StandardText} = entity.${Column.StandardText}, 35 #end 36 #end 37 CreateTime = DateTime.Now 38 }); 39 this.unitOfWork.Commit(); 40 41 return true; 42 } 43 44 public bool Update(${ClassName}CURequest entity) 45 { 46 var tmp = this.repository.Get(entity.Id); 47 if (tmp != null) 48 { 49 #foreach($Column in $ColumnList) 50 #if(${Column.StandardText}!="CreateTime") 51 tmp.${Column.StandardText} = entity.${Column.StandardText}; 52 #end 53 #end 54 this.repository.Update(tmp); 55 56 this.unitOfWork.Commit(); 57 return true; 58 } 59 60 return false; 61 } 62 63 public bool Delete(Guid Id) 64 { 65 this.repository.Delete(Id); 66 this.unitOfWork.Commit(); 67 68 return true; 69 } 70 71 public ${ClassName} Get(Guid Id) 72 { 73 return this.repository.Get(Id); 74 } 75 76 public Tuple<int, IEnumerable<${ClassName}>> GetPage(Page page, Expression<Func<${ClassName}, bool>> order, Expression<Func<${ClassName}, bool>> where = null) 77 { 78 return this.repository.GetPage(page, order, where); 79 } 80 } 81 }
实体类:{0}.cs
1 using System; 2 using Infrastructure.Common; 3 using System.ComponentModel.DataAnnotations; 4 5 namespace Business.ReverseDDD.Model 6 { 7 public class ${ClassName} 8 { 9 [Required] 10 [IgnoreProperty(true)] 11 public int RowNumber { get; set; } 12 13 #foreach($Column in $ColumnList) 14 #if($Column.StandardType == "string") 15 /// <summary>${Column.Description}</summary> 16 public string ${Column.StandardText} { get; set; } 17 18 #else 19 #if(${Column.StandardText}!="Id") 20 /// <summary>${Column.Description}</summary> 21 public $Column.StandardType? ${Column.StandardText} { get; set; } 22 23 #else 24 /// <summary>${Column.Description}</summary> 25 public $Column.StandardType ${Column.StandardText} { get; set; } 26 27 #end 28 #end 29 #end 30 } 31 }
可以看到,所有类名都被{类名}替换掉了,而且支持循环字段,如这个:#foreach($Column in $ColumnList)
以及if语法,如这个:#if(${Column.StandardText}!="CreateTime")
5、我们把所有表需要生成模板批量导出来
好了,把文件拷贝进项目中
6、编译文件、运行单元测试
一个ERROR都没有,当然设置模板时要细心
103个测试用例全部通过,这初步保证了代码质量;
7、预览UI界面
都运行正常,期间一句都没改过哦;当然有些细节肯定要调整的,比如在VIEW视图共性可能不多,很多细节可能需要调整
但是其他层都保证的CURD及GetPage、GetList,这已经完成了至少70%的代码,这真正做到了把主要经历放在业务逻辑层了
老板再也不用担心我的速度问题,so easy!!