经过了上篇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. 各种加密解密函数(URL加密解密、sha1加密解密、des加密解密)

    原文:各种加密解密函数(URL加密解密.sha1加密解密.des加密解密) 普通hash函数如md5.sha1.base64等都是不可逆函数.虽然我们利用php可以利用这些函数写出可逆函数来.但是跨语 ...

  2. Python学习笔记16:标准库多线程(threading包裹)

    Python主要是通过标准库threading包来实现多线程. 今天,互联网时代,所有的server您将收到大量请求. server要利用多线程的方式的优势来处理这些请求,为了改善网络port读写效率 ...

  3. 怎样下载并编译Android4.0内核源代码goldfish(图文)

    关于怎样下载Android4.0源代码,请查看我的博客内还有一篇文章(相同是图文教程): http://blog.csdn.net/flydream0/article/details/7036156 ...

  4. iOS7 UIKit动力学-碰撞特性UICollisionBehavior 上

    我们谈到了重力上述财产UIGravityBehavior这个类. 非常明确的看法,当我们添加的属性的严重性后,,苹果UIview像掉进无底洞,地下坠,不断的加速.而如今呢,我们要在这个手机屏幕上,加入 ...

  5. Java获取系统相关信息System.getProperty()

    java.version Java 运行时环境版本 java.vendor Java 运行时环境供应商 java.vendor.url Java 供应商的 URL java.home Java 安装目 ...

  6. 快速构建Windows 8风格应用5-ListView数据控件

    原文:快速构建Windows 8风格应用5-ListView数据控件 本篇博文主要介绍什么是ListView数据控件.如何构建ListView数据控件. 什么是ListView数据控件? 1)  Li ...

  7. 学习PHP时的一些总结(四)

    目录的基本操作: 在系统的每个目录下都有两个特殊的目录"."和".." , 分别指示当前目录和当前目录的父目录. dirname()  返回目录的名称 path ...

  8. Effective C++ Item 46 当需要投你非成员函数定义模板

    本文senlie原版的,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:当我们编写一个 class template, 而它所提供之"与此 temp ...

  9. 异常:必须先将 ContentLength 字节写入请求流,然后再调用 [Begin]

    异常描述 异常:必须先将 ContentLength 字节写入请求流,然后再调用 [Begin] 解决方案 //解决异常:必须先将 ContentLength 字节写入请求流,然后再调用 [Begin ...

  10. Mysql高级之权限检查原理

    原文:Mysql高级之权限检查原理 用户进行数据库操作分为两步: 1 是否有权限连接,根据host,name,password: 2 是否有权限进行CURD: 图示解说: 关于用户权限在哪里进行存放? ...