CRUD全栈式编程架构之更精简的设计
精简的程度
- ViewModel精简
- 服务精简
- 控制器精简
- Index.cshmtl精简
- AddOrEdit.cshtml精简
效果:最精简的情况下,只需要写Entity这一个数据库实体然后加上一些简单标记即可, 一般情况也只需要写TSearch,TOrder的逻辑可以
ViewModel精简
- 首先明确,因为Entity是codefirst生成数据库的前提,所以这个是必须有的。但是很多情况下 ViewModel和Entity属性一样,这个时候我们可以无需创建ViewModel,让Entity继承自IViewModel 即可将ViewModel精简掉。
- 注意服务中Convert方法不能去掉,由于ef代理对象的存在,直接暴露代理对象到界面层, 如果界面层修改代理对象,并且调用了工作单元的提交,那么实体就会被更新。也许这个bug你会找很久 ,所以Convert方法必须保留
服务的精简
- 第一步我们将Curd服务上的abstract去掉,
- 假设我们知道TEntiy,TModel,TOrder,TSearch的类型就可以通过反射创建出Crud服务了, 那么我们需要将上面四个泛型类型绑定到一起即可,我们可以定义一个类CrudCoden,这个类包含四个 属性,属性的类型都是Type,作用就是用来标识这四个泛型类型.
- 我们设计一个函数,入参是CurdCoden,出参是Curd服务的类型和Curd服务接口类型.通过反射即可构造
- 填充CrudCoden,我们将CrudCoden继承自Attribute,然后给出构造函数传入 TOrder,TModel,TEntity,TSearch,可以重载多个,这样直接标记在TEntity上即可完成CrudCoden的构造
- 注册服务 跟Repository的构造类似,反射程序集,然后获取所有的CurdCodenAttribute,然后 之前的函数获取Crud服务类型和接口类型,然后用Ioc注册即可,。
控制器的精简
- 控制器的注册和Crud服务类似,只是这个不需要接口
- 控制器激活,假设前台传入的url为user/index这种,这时,我们可以拿到controller的类型为user 然后通过反射获取到Entity的类型,这样就可以拿到Crud控制器类型,即可激活控制器
- 注意Url的配置,之前因为定义了Controller的类型,mvc会默认采用{名称}Controller中名称 作为Url中Controller部分的惨呼声,那么在配置url的时候,我们这里默认就采用Entity的名字显式 指定为Contoller参数
Index.cshtml精简
- Controller的返回不在直接是View()这样,我们显式指定未Shared的Index.cshtml页面, 然后页面的Model为dynamic,然后在querysection部分直接Html.EditForModel()即可
- Crud这些按钮也不是都需要,同样通过标记,在Entity上给出自定义Attribute,配置那些功能, 然后在页面上反射获取,如果没有标记,默认为全部.
AddOrEdit.cshtml精简
这里精简和Index.cshtml中类似,指定到特定页面,用dynamic传递模型,用EditForModel生成页面
菜单
这里同样可以通过标识,标识这个实体的Crud可以挂在那个菜单相面,在初始化的时候直接读取 标记即可
几个过程
程序启动过程
- 反射初始化菜单
- 注册Repository
- 注册服务
- 注册控制器
菜单点击过程
- 解析出Url中Controller对应的那个Entity,
- 用IocResolve出Controller,由于使用Ioc,只要构造过类型就可以递归创建
- 执行Action返回index.html页面
- 获取Entity上操作配置,生成页面返回到浏览器
- 调用Html.EditForModel生成页面
- Js调用查询方法获取数据
按钮点击过程
- 解析出Url中Controller对应的那个Entity,
- 用Ioc解析出Controller,由于使用Ioc,只要构造过类型就可以递归创建
- 执行Action返回操作页面
- 调用Html.EditForModel生成页面
- 提交数据(这里默认提交到当前url)
- 重复上述1,2两步,然后提交数据
GetFilter和GetOrder
这两部分需要扩展到TSearch和TOrder的类中即可,并且在SearchBase和OrderBase中声明 虚方法,给出默认实现和Crud服务中一样,然后子类实现
注意
- 这种精简模式并不和之前的冲突,如果有显式实现的Curd服务和控制器则使用精简模式。
- TModel的精简可根据情况使用
- 为了性能考虑,请多做一些缓存
- 精简模式下,其实TModel搭配attribute可以更灵活的实现编辑页面,吧Html.EditForModel 重写掉可以更大程度的是编辑页面灵活
总结
上面已经把实现要做的所有细节都说清楚了,只要按照说明写代码实现即可,最难也就是反射 和attribute的运用了,这两个使用是程序员进阶的必经之路,所以还是必须会的。由于这个设计 其实是一个反模式,太过于集中并且太依赖于配置,调试也相对麻烦。 但是他有一个好处就是帮你少写代码,有时候为了少写些代码很多事情都是值得去尝试的。 如果实现起来遇到什么麻烦,请留言我会一一解答。 代码根本没有思想重要。思想都不重视,代码只是复制粘贴而已。