EF架构~引入规约(Specification)模式_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > EF架构~引入规约(Specification)模式

EF架构~引入规约(Specification)模式

 2013/8/15 2:43:48  蒋叶湖  博客园  我要评论(0)
  • 摘要:规约(Specification)模式:第一次看到这东西是在microsoftNLayer项目中,它是微软对DDD的解说,就像petshop告诉了我们MVC如何使用一样,这个规约事实最重要的作用是实现了查询语句与查询条件的分离,查询语句在底层是稳定的,不变的,而查询条件是和具体业务,具体领域有关的,是易变的,如果我们为每一个领域的每一个新需求都写一个新的方法,那就会出现很多重复的代码,不利于程序的最终扩展!下面我们来看一个经典例子一个IOrderRepository的接口
  • 标签:模式 架构

class="p0">规约(Specification)模式:第一次看到这东西是在microsoft NLayer项目中,它是微软对DDD的解说,就像petshop告诉了我们MVC如何使用一样,这个规约事实最重要的作用是实现了查询语句与查询条件的分离,查询语句在底层是稳定的,不变的,而查询条件是和具体业务,具体领域有关的,是易变的,如果我们为每一个领域的每一个新需求都写一个新的方法,那就会出现很多重复的代码,不利于程序的最终扩展!

下面我们来看一个经典例子

一个IOrderRepository接口,定义了一个订单仓储

        Order_Info GetOrder_InfoById(int orderID);  

        List<Order_Info> GetOrder_Info(DateTime from, DateTime to);                    

       List<Order_Info> GetOrder_InfoByUser(int userID);


代码本身没有任何问题,你只要去实现它就可以了,当一个新的需求到了之后,你的接口要被扩展(这是不被提倡的,一般我们会新建一个接口),然后修改

原来的实现类,去实现接口新的方法(违背了OCP原则),这种做法是大多部开发团队所起用偶尔了,我,一个普通的人,也起用偶尔了,但当我知道DDD后,当我看完

microsoft Nlayer项目之后,我知道,我一定要改变这种局面,于是,代码在规约模式的指导下,进行重构了,呵呵。

先看一下规约模式的类关系图

 

下面是我对原来结构的修改(由于原程序是三层架构,所以我就不改变原有架构了,只是对代码进行重构,DAL层,BLL层,WEB层)

DAL

IRepository仓储接口如下,怎么去实现就不放了,呵呵

public interface IRepository<TEntity>     where TEntity : class    {    

    /// <summary>    

/// 通用表达式树,得到实体

 ///</summary>///<param name="predicate"></param>///<returns></returns>

    TEntity GetEntity(Expression<Func<TEntity, bool>> predicate); 

/// <summary> 

/// Get all elements of type {T} in repository /// </summary> 

/// <returns>List of selected elements</returns>

 IQueryable<TEntity> GetEntities(); 

/// <summary> /// Get all elements of type {T} that matching a 

/// Specification <paramref name="specification"/> /// </summary> 

/// <param name="specification">Specification that result meet</param> 

/// <returns></returns>

 IQueryable<TEntity> GetEntities(ISpecification<TEntity> specification); 

/// <summary> /// 通用表达式树,得到集合 /// </summary>

 /// <param name="predicate"></param> /// <returns></returns>

 IQueryable<TEntity>GetEntities(Expression<Func<TEntity,bool>> predicate); 

}

IOrderRepository接口如下

 public interface IOrderRepository :        Domain.Core.IRepository<Order_Info>

   {       

          void InsertOrder(Order_Info entity); 

   }

DAL底层为数据持久化层,它是非常稳定的,只提供最基本的表操作,具体业务如何组成,全放在BLL层去实现

BLL

这一层中定义具体业务的规约,并组成查询方法及调用DAL层的具体方法(DAL层来接受从BLL层传过来的ISpecification参数)

/// <summary> 

 /// <summary>    /// 根据下单日期得到订单列表    /// </summary>  

  public class OrderFromDateSpecification : Specification<Order_Info>  

  {    

   DateTime? _fromDate;     

   DateTime? _toDate;      

  public OrderFromDateSpecification(DateTime? fromDate, DateTime? toDate)     

   {   

         _fromDate = fromDate ?? DateTime.MinValue;   

         _toDate = toDate ?? DateTime.MaxValue;    

    }   

     public override global::System.Linq.Expressions.Expression<Func<Order_Info, bool>> SatisfiedBy()    

    {      

 

      Specification<Order_Info> spec = new TrueSpecification<Order_Info>(); 

spec &= new DirectSpecification<Order_Info>(o => o.CreateDate >= _fromDate && o.CreateDate <= _toDate); 

return spec.SatisfiedBy(); 

}  

 /// <summary>    /// 通过用户信息得到他的订单列表    /// </summary>   

 public class OrderFromUserSpecification : Specification<Order_Info>   

 {   

     int _userID = default(Int32);      

  public OrderFromUserSpecification(int userID)    

{           

 _userID = userID;   

     }  

  public override global::System.Linq.Expressions.Expression<Func<Order_Info, bool>> SatisfiedBy()     

   {       

     Specification<Order_Info> spec = new TrueSpecification<Order_Info>();            spec &= new DirectSpecification<Order_Info>(o => o.UserID == _userID);            return spec.SatisfiedBy();    

    }   

 }

业务层真实的查询主体,只要在一个方法里写就OK了,然后它非常稳定,如果以后还有其它查询业务出来,直接添加一个查询规约即可

       /// <summary>        /// 根据WEB层传来及组件好的规约,返回集体       

  /// </summary>        

/// <param name="spec"></param>    

/// <returns></returns>      

  public List<Order_Info> GetOrder_InfoBySpec(ISpecification<Order_Info> spec)        {           

 return _iOrderRepository.GetEntities(spec).ToList();  

      }

 

WEB

Web层建立一个指定的规约,并为规约组件所需要的数据即可

        public ActionResult List(int? userID)        {        

   ISpecification<Order_Info> spec = new OrderFromUserSpecification(userID ?? 0);  

          var model = orderService.GetOrder_InfoBySpec(spec);      

      return View(model);       

 }

如果这时来了个新需要,使用用户名进行查询,你可以直接建立一个OrderFromUserNameSpecification的规约即可,而不需要修改OrderService,呵呵!

发表评论
用户名: 匿名