架构,改善程序复用性的设计~第六讲 我的系统结构~将所有可以抽象的项目进行抽象(大结局)
N层架构及各层之间的通讯标准
一 总体结构图
二 各个模块的介绍
通用项目模块Project.Common:它是对所有项目都公开的项目组合,主要提供一个与领域无关的通用功能的代码库
核心项目模块Project.Core:它是针对某种构架方式(如LINQ To SQL作为底层架构)抽象出来的项目组合,它与领域无关
领域项目模块,它是具体的项目,如XXB项目,它本身也是一个N层架构方式,一般地,它的UI层会继承我们的Product.Core下的Web.Commons项目,而对应的Entity对应Entity.Commons项目,由于BLL层是针对某种特殊业务领域的,所以在Project.Core里没有出现BLL层的抽象。
以下是一个Demo项目的结构
三 具体领域模块各层之间的通讯标准
由于 project.common和project.core是比较稳定的,而且对所有解决方案都是共用的,所以在这里它不是我们讨论的重点,我们主要说一下具体领域模块的各层间的通讯问题
领域模块总体图:
3.1 UI层与BLL层通讯
添加删除与更新操作统一使用实体类型,如果要返回信息,请使用统一的消息类
1 /// <summary> 2 /// 插入商品 3 /// </summary> 4 VMessage AddProduct(Product entity);
而查询使用统一使用一个字典类型来存储条件,用一个结构体存储分页参数
1 /// <summary> 2 /// 根据条件得到分页结果集 3 /// </summary> 4 /// <param name="vp"></param> 5 /// <param name="pp"></param> 6 /// <returns></returns> 7 PagedList<Product> GetProduct(VPredication vp, PagingParam pp);
3.2 BLL层与DAL层通讯
BLL层将数据进行组合后,调用数据层统一的方法即可,数据层只提供最基础的GURD操作,涉及到多表插入,查询的,统一在BLL层进行组合实现。
下面是业务层代码的实现:
1 /// <summary> 2 /// 商品模块实现 3 /// </summary> 4 public class ProductService : ServiceBase, IProductService 5 { 6 IProductRepository iProductRepository = null; 7 public ProductService() 8 { 9 iProductRepository = new ProductRepository(); 10 } 11 12 #region IProductService 成¨¦员¡À 13 public Entity.VMessage AddProduct(Entity.Car_Rental.Product entity) 14 { 15 try 16 { 17 iProductRepository.Insert(entity); 18 VMessage.IsComplete = true; 19 } 20 catch (Exception) 21 { 22 // throw; //发布后注释它¨¹ 23 VMessage.IsComplete = false; 24 } 25 return VMessage; 26 } 27 public Entity.PagedList<Entity.Car_Rental.Product> GetProduct(Entity.VPredication vp, Entity.PagingParam pp) 28 { 29 var linq = iProductRepository.GetDetailModel(); 30 return new Entity.PagedList<Entity.Car_Rental.Product>(linq, pp.PageIndex, pp.PageSize); 31 } 32 #endregion 33 }
四 实体验证机制
应该是一种前台特殊效果验证和实体有效性验证相结合的一种验证方式,前台验证一般指JS验证,可能产生一些用户体验比较好的效果,实体验证多在实体层完成,在进行添加,修改等操作时,需要进行些验证。
4.1 实体统一基类:
在EntityBase类中已经完成了对实体非空的验证,GetRuleViolations方法将返回验证失败的迭代结果集,它是一个虚方法,子类可以根据自己的逻辑去复写它。IsValid是一个属性,它在判断实体验证时被赋值,为true表示成功,反之,验证失败。
对于复合实体,如在前台表单中可以出现多个实体组合的情况,这时,可以使用MVC的那种方法,页面元素写在一个ViewModel里,供这个页面视图使用,使用.net的attribute 很容易的可以实现属性的验证。
在controller层(可能根据业务需要,也会被抽象出来),我们在进行实体添加与修改操作时,需要判断实体的IsValid,然后再去调用BLL层的方法,一般代码是这样:
1 [HttpPost] 2 public ActionResult Create(FormCollection collection) 3 { 4 News entity = new News(); 5 TryUpdateModel(entity); 6 entity.CreateDate = DateTime.Now; 7 entity.UpdateDate = DateTime.Now; 8 entity.Status = (int)Status.Normal; 9 if (entity.IsValid) 10 { 11 iNewsRepository.Insert(entity); 12 return AlertToUrl("Index"); 13 } 14 else 15 { 16 entity.GetRuleViolations().ToList().ForEach(i => 17 { 18 ModelState.AddModelError(i.PropertyName, i.ErrorMessage); //验证没有通过的信息 19 }); 20 } 21 return View(); 22 }
五 接口的重要性
接口可能会成功我们的累赘,添加了代码量,(F12)转到定义时也会带来不方便,我们是否应该废弃接口
它的好处:
1 统一,稳定的操作规范
2 使用接口,配和IOC,实现一种操作的多种实现方式的切换
对DAL层接口与实现的抽象图示