经过了上篇IRepositoryIRepository<T>的讨论【文章地址为:http://www.cnblogs.com/yomho/p/3296759.html

我选择了IRepository作为我重构框架的仓储接口

一、接口定义  

新的IRepository接口设计如下:

 namespace Yom.NFramework2_0
{
public interface IRepository<TCompositeKey>
where TCompositeKey : IEquatable<string>
{
#region 实体操作接口
T FindBy<T>(TCompositeKey primaryKey) where T : IEntity;
IEnumerable<T> FindAll<T>() where T : IEntity;
IEnumerable<T> FindAll<T>(IWhere[] where) where T : IEntity;
IEnumerable<T> FindAll<T>(IWhere[] where, IOrder[] order) where T : IEntity;
IEnumerable<T> FindAll<T>(int pageIndex, int pageSize, IWhere[] where, IOrder[] order, out int count) where T : IEntity;
void Add<T>(T entity) where T : IEntity;
void Delete<T>(T entity) where T : IEntity;
void DeleteAll<T>() where T : IEntity;
void DeleteAll<T>(IWhere[] where) where T : IEntity;
void DeleteAll<T>(string where) where T : IEntity;
void DeleteAll<T>(IEnumerable<TCompositeKey> pkValues) where T : IEntity;
void Update<T>(T entity) where T : IEntity;
bool Exists<T>(TCompositeKey primaryKey) where T : IEntity;
#endregion
#region 静态方法接口
int ExecuteSql(string sql, params System.Data.IDataParameter[] ps);
object ExecuteScalar(string sql, params System.Data.IDataParameter[] ps);
System.Data.DataTable ExecuteDataTable(string sql, params System.Data.IDataParameter[] ps);
#endregion
}
}

其中IEntity和IWhere以及IOrder的设计接口如下:

public interface IEntity
{
}
public interface IOrder
{
}
public interface IWhere
{
}
public interface ICompositeKey : IEquatable<string>
{
}

ICompositeKey为组合主键接口

为什么ICompositeKey要继承为IEquatable<string>这个接口呢?

因为IEquatable<string>是string的基类,且string为不能继承的类,

所以目的是和string兼容,经过处理可以变成一个string类,从而可以兼容普通的非组合主键。

(此文不讲组合主键的实现原理,展示组合主键接口只是让大家看看组合主键实现解耦的方法)

二、嫁接Castle实现搜索以及排序

很多人不知道怎么把自己的IRepository接口的排序和搜索对象解耦,

在用不同的ORM实现IRepository接口的时候总不知道怎么弄排序和搜索

下面就来看我怎么把Castle的排序和搜索用IOrder以及IWhere解耦的

首先是IOrder -> NHibernate.Expression.Order 的变身

 namespace Yom.NFramework2_0.CastleExtend
{
public class OrderBase : NHibernate.Expression.Order, Yom.NFramework2_0.IOrder
{
public OrderBase(string propertyName, bool ascending) : base(propertyName, ascending) { }
}
}

这个很简单,OrderBase一下子就变成了NHibernate.Expression.Order

那么IWhere是否可以顺利完成像IOrder这种变身么?

研究后发现:Castle是用NHibernate.Expression.Expression的静态方法创建查询对象的

静态方法都是返回NHibernate.Expression.AbstractCriterion抽象类或者ICriterion接口

可以继承这个抽象对象或者接口吧,这样就可以实现变身了!!!

但如果真要这样做,必然有抽象方法要实现,这实在是一个下下策(想嫁接个接口和抽象类不容易吖)

那有没有直接实现NHibernate.Expression.AbstractCriterion抽象类的类呢?

反正我是没有找到,但是Castle肯定有,如果找到这么个类,就可以像IOrder一样实现嫁接,现在没有发现只能想他法。

最后我对WhereBase的变身是:

 namespace Yom.NFramework2_0.CastleExtend
{
public class WhereBase : Yom.NFramework2_0.IWhere
{
public NHibernate.Expression.ICriterion Instance
{
get;
set;
}
public override string ToString()
{
return Instance.ToString();
}
#region 废弃代码
//public static void AllEq(WhereBase where, System.Collections.IDictionary propertyNameValues)
//{
// where.Instance = NHibernate.Expression.Expression.AllEq(propertyNameValues);
//}
//public static void And(WhereBase where, WhereBase whereA, WhereBase whereB)
//{
// where.Instance = NHibernate.Expression.Expression.And(whereA.Instance, whereB.Instance);
//}
//public static void Between(WhereBase where, string propertyName, object lo, object hi)
//{
// where.Instance = NHibernate.Expression.Expression.Between(propertyName, lo, hi);
//}
//public static void Eq(WhereBase where, string propertyName, object value) {
// where.Instance = NHibernate.Expression.Expression.Eq(propertyName, value);
//}
//public static void EqProperty(WhereBase where, string propertyName, string otherPropertyName)
//{
// where.Instance = NHibernate.Expression.Expression.EqProperty(propertyName, otherPropertyName);
//}
//public static void Ge(WhereBase where, string propertyName, object value)
//{
// where.Instance = NHibernate.Expression.Expression.Ge(propertyName, value);
//}
//public static void GeProperty(WhereBase where, string propertyName, string otherPropertyName)
//{
// where.Instance = NHibernate.Expression.Expression.GeProperty(propertyName, otherPropertyName);
//}
//public static void Gt(WhereBase where, string propertyName, object value)
//{
// where.Instance = NHibernate.Expression.Expression.Gt(propertyName, value);
//}
//public static void GtProperty(WhereBase where, string propertyName, string otherPropertyName)
//{
// where.Instance = NHibernate.Expression.Expression.GtProperty(propertyName, otherPropertyName);
//}
//public static void IdEq(WhereBase where, object value)
//{
// where.Instance = NHibernate.Expression.Expression.IdEq(value);
//}
//public static void In(WhereBase where, string propertyName, System.Collections.ICollection values)
//{
// where.Instance = NHibernate.Expression.Expression.In(propertyName, values);
//}
//public static void InG<T>(WhereBase where, string propertyName, ICollection<T> values)
//{
// where.Instance = NHibernate.Expression.Expression.InG<T>(propertyName, values);
//}
//public static void InsensitiveLike(WhereBase where, string propertyName, object value)
//{
// where.Instance = NHibernate.Expression.Expression.InsensitiveLike(propertyName, value);
//}
//public static void IsEmpty(WhereBase where, string propertyName)
//{
// where.Instance = NHibernate.Expression.Expression.IsEmpty(propertyName);
//}
//public static void propertyName(WhereBase where, string propertyName)
//{
// where.Instance = NHibernate.Expression.Expression.IsNotEmpty(propertyName);
//}
//public static void IsNotNull(WhereBase where, string propertyName)
//{
// where.Instance = NHibernate.Expression.Expression.IsNotNull(propertyName);
//}
//public static void IsNull(WhereBase where, string propertyName)
//{
// where.Instance = NHibernate.Expression.Expression.IsNull(propertyName);
//}
//public static void Le(WhereBase where, string propertyName, object value)
//{
// where.Instance = NHibernate.Expression.Expression.Le(propertyName, value);
//}
//public static void LeProperty(WhereBase where, string propertyName, string otherPropertyName)
//{
// where.Instance = NHibernate.Expression.Expression.LeProperty(propertyName, otherPropertyName);
//}
//public static void Like(WhereBase where, string propertyName, string value, NHibernate.Expression.MatchMode matchModes)
//{
// where.Instance = NHibernate.Expression.Expression.Like(propertyName, value, matchModes);
//} //public static void Lt(WhereBase where, string propertyName, object value)
//{
// where.Instance = NHibernate.Expression.Expression.Lt(propertyName, value);
//}
//public static void LtProperty(WhereBase where, string propertyName, string otherPropertyName)
//{
// where.Instance = NHibernate.Expression.Expression.LtProperty(propertyName, otherPropertyName);
//}
//public static void Not(WhereBase where)
//{
// where.Instance = NHibernate.Expression.Expression.Not(where.Instance);
//}
//public static void NotEqProperty(WhereBase where, string propertyName, string otherPropertyName)
//{
// where.Instance = NHibernate.Expression.Expression.NotEqProperty(propertyName, otherPropertyName);
//}
//public static void Or(WhereBase where, WhereBase whereA, WhereBase whereB)
//{
// where.Instance = NHibernate.Expression.Expression.Or(whereA.Instance, whereB.Instance);
//}
//public static void Sql(WhereBase where, string sql)
//{
// where.Instance = NHibernate.Expression.Expression.Sql(sql);
//}
#endregion
}
}

最好注释也去掉,这样的好处是别人开发的可以不管ORM是用什么第三方框架,直接调用WhereBase静态方法(代理模式)

WhereBase直接携带了Castle的搜索接口ICriterion,

在RepositoryBase有个这么个方法转换IWhere为Castle的搜索对象

 #region 其他方法
NHibernate.Expression.ICriterion[] IWhere2ICriterion(IWhere[] where)
{
if (where == null) {
return null;
}
NHibernate.Expression.ICriterion[] wheres = new NHibernate.Expression.ICriterion[where.Length];
for (var i = ; i < where.Length; i++)
{
wheres[i] = (where[i] as WhereBase).Instance;
}
return wheres;
}
#endregion

这样就可以完美地实现搜索和排序的解耦

仓储基类有个方法实现如下:

 public IEnumerable<T> FindAll<T>(IWhere[] where) where T : IEntity
{
if (where == null) {
return FindAll<T>();
}
return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(IWhere2ICriterion(where));
}

三、总结:    

1:搜索和排序的解耦不算是个难题

2: 实现的仓储基类可以通过IoC注入实例化,这样可以插拔式更换ORM

3: 定义的仓储接口和实现最好放在不同的类库,以更好的解耦

四、后记:Repository实现仓储--Castle实现      

 namespace Yom.NFramework2_0.CastleExtend
{
public abstract class EntityBase : Castle.ActiveRecord.ActiveRecordBase, Yom.NFramework2_0.IEntity
{
}
}

实体基类嫁接

 namespace Yom.NFramework2_0
{
public interface ISinglePrimaryKeyRepository : IRepository<string>
{
}
}

非组合主键仓储扩展

 namespace Yom.NFramework2_0.CastleExtend
{
public class CastleSinglePrimaryKeyRepository : ISinglePrimaryKeyRepository//, System.Configuration.IConfigurationSectionHandler
{
#region IRepository<string> 成员 #region 实体相关操作
public T FindBy<T>(string primaryKey) where T : IEntity
{
return Castle.ActiveRecord.ActiveRecordBase<T>.Find(primaryKey);
} public IEnumerable<T> FindAll<T>() where T : IEntity
{
return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll();
} public IEnumerable<T> FindAll<T>(IWhere[] where) where T : IEntity
{
if (where == null) {
return FindAll<T>();
}
return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(IWhere2ICriterion(where));
} public IEnumerable<T> FindAll<T>(IWhere[] where, IOrder[] order) where T : IEntity
{
if (order == null)
{
if (where == null)
{
return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll();
}
else
{
return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(IWhere2ICriterion(where));
}
}
else if (where == null)
{
return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(order as NHibernate.Expression.Order[]);
} return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(order as NHibernate.Expression.Order[], IWhere2ICriterion(where));
} public IEnumerable<T> FindAll<T>(int pageIndex, int pageSize, IWhere[] where, IOrder[] order, out int count) where T : IEntity
{
if (where == null)
{
count = Castle.ActiveRecord.ActiveRecordMediator.Count(typeof(T));
if (order == null) {
return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize); }else{
return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize, order as NHibernate.Expression.Order[]);
}
}
else
{
count = Castle.ActiveRecord.ActiveRecordMediator.Count(typeof(T), IWhere2ICriterion(where));
if (order == null) {
return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize, IWhere2ICriterion(where));
}
}
return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize, order as NHibernate.Expression.Order[], IWhere2ICriterion(where));
} public void Add<T>(T entity) where T : IEntity
{
using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
{
(entity as Castle.ActiveRecord.ActiveRecordBase).CreateAndFlush();
tran.VoteCommit();
}
} public void Delete<T>(T entity) where T : IEntity
{
using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
{
(entity as Castle.ActiveRecord.ActiveRecordBase).DeleteAndFlush();
tran.VoteCommit();
}
} public void DeleteAll<T>() where T : IEntity
{
using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
{
Castle.ActiveRecord.ActiveRecordBase<T>.DeleteAll();
tran.VoteCommit();
}
} public void DeleteAll<T>(IWhere[] where) where T : IEntity
{
IEnumerable<T> entities;
if (where == null)
{
entities = this.FindAll<T>();
}
else
{
entities = this.FindAll<T>(where);
}
if (entities != null)
{
using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
{
foreach (T entity in entities) {
this.Delete<T>(entity);
}
tran.VoteCommit();
}
}
}
public void DeleteAll<T>(string where) where T : IEntity
{ using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
{
Castle.ActiveRecord.ActiveRecordBase<T>.DeleteAll(where);
tran.VoteCommit();
} }
public void DeleteAll<T>(IEnumerable<string> pkValues) where T : IEntity
{
using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
{
Castle.ActiveRecord.ActiveRecordBase<T>.DeleteAll(pkValues);
tran.VoteCommit();
}
} public void Update<T>(T entity) where T : IEntity
{
using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
{
(entity as Castle.ActiveRecord.ActiveRecordBase).UpdateAndFlush();
tran.VoteCommit();
}
} public bool Exists<T>(string primaryKey) where T : IEntity
{
return Castle.ActiveRecord.ActiveRecordBase<T>.Exists<string>(primaryKey);
}
#endregion
#region ado执行sql
public int ExecuteSql(string sql, params System.Data.IDataParameter[] ps)
{
using (System.Data.IDbCommand cmd = Castle.ActiveRecord.ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(CastleSinglePrimaryKeyRepository)).Connection.CreateCommand())
{
cmd.CommandText = sql;
if (ps != null && ps.Length > )
{
foreach (System.Data.IDataParameter p in ps)
{
cmd.Parameters.Add(p);
}
}
return cmd.ExecuteNonQuery();
}
} public object ExecuteScalar(string sql, params System.Data.IDataParameter[] ps)
{
using (System.Data.IDbCommand cmd = Castle.ActiveRecord.ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(CastleSinglePrimaryKeyRepository)).Connection.CreateCommand())
{
cmd.CommandText = sql;
if (ps != null && ps.Length > )
{
foreach (System.Data.IDataParameter p in ps)
{
cmd.Parameters.Add(p);
}
}
return cmd.ExecuteScalar();
}
} public System.Data.DataTable ExecuteDataTable(string sql, params System.Data.IDataParameter[] ps)
{
using (System.Data.IDbCommand cmd = Castle.ActiveRecord.ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(CastleSinglePrimaryKeyRepository)).Connection.CreateCommand())
{
cmd.CommandText = sql;
if (ps != null && ps.Length > )
{
foreach (System.Data.IDataParameter p in ps)
{
cmd.Parameters.Add(p);
}
}
System.Data.DataTable result = new System.Data.DataTable();
result.Load(cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection));
return result;
}
}
#endregion
#endregion
#region 其他方法
NHibernate.Expression.ICriterion[] IWhere2ICriterion(IWhere[] where)
{
if (where == null) {
return null;
}
NHibernate.Expression.ICriterion[] wheres = new NHibernate.Expression.ICriterion[where.Length];
for (var i = ; i < where.Length; i++)
{
wheres[i] = (where[i] as WhereBase).Instance;
}
return wheres;
}
#endregion
}
}

Castle实现IReposoitory

五、项目开发的层次结构                                                                                              

【Yom框架】漫谈个人框架的设计之二:新的IRepository接口+搜索和排序解耦(+基于Castle实现)的更多相关文章

  1. JAVA经常使用集合框架使用方法具体解释基础篇二之Colletion子接口List

    接着上一篇,接着讲讲集合的知识.上一篇讲了Collection接口.它能够说是集合的祖先了,我们这一篇就说说它的子孙们. 一.Collection的子接口 List:有序(存入和取出的顺序一致).元素 ...

  2. 【Yom框架】漫谈个人框架的设计之一:是IRepository还是IRepository<T>?

    前言                                                                                                   ...

  3. 基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集【转】

    转自:http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html 一直想把USB摄像头接到Zedboard上,搭建 ...

  4. 【Yom框架】漫谈个人框架的设计之三:业务接口+UI层的设计(基于Castle实现的Repository)

    Repository层设计的文章见:[http://www.cnblogs.com/yomho/p/3297042.html]   一.概要设计 上面Reposity 应该为 Repository 特 ...

  5. 从MVC框架看MVC架构的设计

    尽管MVC早已不是什么新鲜话题了,但是从近些年一些优秀MVC框架的设计上,我们还是会发现MVC在架构设计上的一些新亮点.本文将对传统MVC架构中的一些弊病进行解读,了解一些优秀MVC框架是如何化解这些 ...

  6. 从MVC框架看MVC架构的设计(转)

    尽管MVC早已不是什么新鲜话题了,但是从近些年一些优秀MVC框架的设计上,我们还是会发现MVC在架构设计上的一些新亮点.本文将对传统MVC架构中的一些弊病进行解读,了解一些优秀MVC框架是如何化解这些 ...

  7. 基于SSH框架的考勤管理系统的设计与实现

    基于SSH框架的考勤管理系统的设计与实现

  8. 基于python的接口测试框架设计(二)配置一些参数及文件

    基于python的接口测试框架设计(二)配置一些参数及文件 我这里需要基于我的项目配置的主要是登陆参数.以及baseURL ,把这些放在单独的文件里  毕竟导入的时候方便了一些 首先是url 图略 建 ...

  9. 好的框架需要好的 API 设计 —— API 设计的六个原则

    说到框架设计,打心底都会觉得很大很宽泛,而 API 设计是框架设计中的重要组成部分.相比于有很多大佬都认可的面向对象的六大原则.23 种常见的设计模式来说,API 设计确实缺少行业公认的原则或者说设计 ...

随机推荐

  1. 了解你的家公家IP

          我们总是在不在家的时候,须要訪问我们的电脑或设备,因为大多数人拥有来自ISP的动态IP,我们能够做一个小型设备来给我们的Android手机发送一个简单的通知,这样我们就能够总有IP用了,有 ...

  2. MAC使用小技巧(一)

    [ Mac OS X 终端命令开启功能 ] 1.Lion下显示资源库方法一:显示在“终端”中输入下面的命令:chflags nohidden ~/Library/ 隐藏在“终端”中输入下面的命令:ch ...

  3. Introducing Visual Studio’s Emulator for Android

    visual studio 2015支持Android开发了. Microsoft released Visual Studio 2015 Preview this week and with it ...

  4. 候选键(unique)

    foreign key references  除了关联外键,还可以关联 候选键(unique) 需求 table1 中的  status  int  类型 ,表示状态 ,0 未启动 ,1 已启动,2 ...

  5. 勾选Create git respository的作用

    在Xcode中创建项目时会弹出Source Control选项,勾选Create git repository选项可以帮助我们对照以前项目中代码中修改的部分,为开发提供方便. 在项目完成到一定程度时, ...

  6. Responsive Design in 3 Steps

    Responsive web design is no doubt a big thing now. If you still not familiar with responsive design, ...

  7. 四大OLAP工具选型浅析

    OLAP(在线分析处理)这个名词是在1993年由E.F.Codd提出来的,只是,眼下市场上的主流产品差点儿都是在1993年之前就已出来,有的甚至已有三十多年的历史了.OLAP产品不少,本文将主要涉及C ...

  8. C# ---- 串口数据YSI实例

    原文:C# ---- 串口数据YSI实例 C#----串口数据接收发送中,发送接收数据已经可以模拟了. 本次YSI实例过程中 主要是:类型转换问题 .计算校验码 一.不同设备不同的规则,本次实例代码如 ...

  9. 一个完整的Installshield安装程序实例—艾泽拉斯之海洋女神出品(四) --高级设置二

    原文:一个完整的Installshield安装程序实例-艾泽拉斯之海洋女神出品(四) --高级设置二 上一篇:一个完整的安装程序实例—艾泽拉斯之海洋女神出品(三) --高级设置一4. 根据用户选择的组 ...

  10. 部分PC端安卓管理器使用强行断开重连的方法来连接手机,容易丢书数据,损坏数据

    最近发现部分PC端的安卓管理器,貌似是百度影音以及PPTV的安卓客户端,使用强行断开手机连接,然后重新连接手机的方法,来实现客户端程序连接手机. 此时,如果刚好正在复制文件,则复制的文件会损坏,并且基 ...