• 项目架构开发:展现层(下)


    上一章我们完成了项目的展现层的一个表的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!!

  • 相关阅读:
    资源汇总
    最近面试经历
    Screen Space Ambient Occlusion
    实时渲染下的多线程协作:实践
    High Dynamic Range
    Deferred Shading
    实时渲染下的多线程协作
    9.了解四个相等判断的用法
    14.使用构造函数链
    16.垃圾最小化
  • 原文地址:https://www.cnblogs.com/lanxiaoke/p/6545650.html
Copyright © 2020-2023  润新知