【Yomフレームワーク】個人フレームワークの設計の2つ:新しいIrepositoryインタフェース+検索とソートデカップリング(+Castleベースで実現)

67051 ワード

前編IrepositoryとIrepositoryの議論を経た【記事アドレス:http://www.cnblogs.com/yomho/p/3296759.html
フレームワークを再構築する倉庫インタフェースとしてIrepositoryを選びました
一、インタフェース定義
新しいIrepositoryインタフェースは次のように設計されています.
 1 namespace Yom.NFramework2_0
 2 {
 3     public interface IRepository<TCompositeKey>
 4         where TCompositeKey : IEquatable<string>
 5     {
 6         #region       
 7         T FindBy<T>(TCompositeKey primaryKey) where T : IEntity;
 8         IEnumerable<T> FindAll<T>() where T : IEntity;
 9         IEnumerable<T> FindAll<T>(IWhere[] where) where T : IEntity;
10         IEnumerable<T> FindAll<T>(IWhere[] where, IOrder[] order) where T : IEntity;
11         IEnumerable<T> FindAll<T>(int pageIndex, int pageSize, IWhere[] where, IOrder[] order, out int count) where T : IEntity;
12         void Add<T>(T entity) where T : IEntity;
13         void Delete<T>(T entity) where T : IEntity;
14         void DeleteAll<T>() where T : IEntity;
15         void DeleteAll<T>(IWhere[] where) where T : IEntity;
16         void DeleteAll<T>(string where) where T : IEntity;
17         void DeleteAll<T>(IEnumerable<TCompositeKey> pkValues) where T : IEntity;
18         void Update<T>(T entity) where T : IEntity;
19         bool Exists<T>(TCompositeKey primaryKey) where T : IEntity;
20         #endregion
21         #region       
22         int ExecuteSql(string sql, params System.Data.IDataParameter[] ps);
23         object ExecuteScalar(string sql, params System.Data.IDataParameter[] ps);
24         System.Data.DataTable ExecuteDataTable(string sql, params System.Data.IDataParameter[] ps);
25         #endregion
26     }
27 }

ここでIEntityとIWhere及びIOrderの設計インタフェースは以下の通りである.
public interface IEntity
    {
    }
public interface IOrder
    {
    }
public interface IWhere
    {
    }
public interface ICompositeKey : IEquatable<string>
    {
    }

ICompositeKeyは結合プライマリ・キー・インタフェース
ICompositeKeyがIEquatableというインタフェースを継承するのはなぜですか?
IEquatableはstringのベースクラスであり、stringは継承できないクラスであるため、
したがって、stringと互換性を目的とし、処理によってstringクラスになり、通常の非組合せプライマリ・キーと互換性を得ることができる.
(本稿では,組合せプライマリ・キーの実現原理を述べず,組合せプライマリ・キー・インタフェースが組合せプライマリ・キーのデカップリングを実現する方法を示す)
 
二、接ぎ木Castleの検索とソートを実現する
多くの人は自分のIrepositoryインタフェースのソートと検索オブジェクトのデカップリングを知らない.
異なるORMでIrepositoryインタフェースを実現する時いつもどのように並べ替えて検索することを知りません
次に、Castleのソートと検索をIOrderとIWhereでデカップリングする方法を見てみましょう.
まずIOrder->NHibernate.Expression.オーダーの変身
1 namespace Yom.NFramework2_0.CastleExtend
2 {
3     public class OrderBase : NHibernate.Expression.Order, Yom.NFramework2_0.IOrder
4     {
5         public OrderBase(string propertyName, bool ascending) : base(propertyName, ascending) { 
6         
7         }
8     }
9 }

これは簡単です.OrderBaseは一気にNHibernateになりました.Expression.Order
 
では、IWhereはIOrderのような変身を無事に果たすことができるのだろうか.
研究の結果、CastleはNHibernateであることが分かった.Expression.Expressionの静的メソッドクエリー・オブジェクトの作成
静的方法はNHibernateを返す.Expression.AbstraactCriterion抽象クラスまたはICriterionインタフェース
この抽象的なオブジェクトやインタフェースを継承して、変身を実现することができます!!!
しかし、もし本当にそうするならば、必然的に抽象的な方法が実現しなければならない.これは本当に下策だ.
それはNHibernateを直接実現したかどうか.Expression.AbstraactCriterion抽象クラスのクラスは?
どうせ見つからなかったのですが、Castleには必ずあります.もしこのようなクラスを見つけたら、IOrderのように接ぎ木を実現することができます.今は発見していません.彼の方法しか考えられません.
最後に私がWhereBaseに変身したのは:
  1 namespace Yom.NFramework2_0.CastleExtend
  2 {
  3     public class WhereBase : Yom.NFramework2_0.IWhere
  4     {
  5         public NHibernate.Expression.ICriterion Instance
  6         {
  7             get;
  8             set;
  9         }
 10         public override string ToString()
 11         {
 12             return Instance.ToString();
 13         }
 14         #region     
 15         //public static void AllEq(WhereBase where, System.Collections.IDictionary propertyNameValues)
 16         //{
 17         //    where.Instance = NHibernate.Expression.Expression.AllEq(propertyNameValues);
 18         //}
 19         //public static void And(WhereBase where, WhereBase whereA, WhereBase whereB)
 20         //{
 21         //    where.Instance = NHibernate.Expression.Expression.And(whereA.Instance, whereB.Instance);
 22         //}
 23         //public static void Between(WhereBase where, string propertyName, object lo, object hi)
 24         //{
 25         //    where.Instance = NHibernate.Expression.Expression.Between(propertyName, lo, hi);
 26         //}
 27         //public static void Eq(WhereBase where, string propertyName, object value) {
 28         //    where.Instance = NHibernate.Expression.Expression.Eq(propertyName, value);
 29         //}
 30         //public static void EqProperty(WhereBase where, string propertyName, string otherPropertyName)
 31         //{
 32         //    where.Instance = NHibernate.Expression.Expression.EqProperty(propertyName, otherPropertyName);
 33         //}
 34         //public static void Ge(WhereBase where, string propertyName, object value)
 35         //{
 36         //    where.Instance = NHibernate.Expression.Expression.Ge(propertyName, value);
 37         //}
 38         //public static void GeProperty(WhereBase where, string propertyName, string otherPropertyName)
 39         //{
 40         //    where.Instance = NHibernate.Expression.Expression.GeProperty(propertyName, otherPropertyName);
 41         //}
 42         //public static void Gt(WhereBase where, string propertyName, object value)
 43         //{
 44         //    where.Instance = NHibernate.Expression.Expression.Gt(propertyName, value);
 45         //}
 46         //public static void GtProperty(WhereBase where, string propertyName, string otherPropertyName)
 47         //{
 48         //    where.Instance = NHibernate.Expression.Expression.GtProperty(propertyName, otherPropertyName);
 49         //}
 50         //public static void IdEq(WhereBase where, object value)
 51         //{
 52         //    where.Instance = NHibernate.Expression.Expression.IdEq(value);
 53         //}
 54         //public static void In(WhereBase where, string propertyName, System.Collections.ICollection values)
 55         //{
 56         //    where.Instance = NHibernate.Expression.Expression.In(propertyName, values);
 57         //}
 58         //public static void InG<T>(WhereBase where, string propertyName, ICollection<T> values)
 59         //{
 60         //    where.Instance = NHibernate.Expression.Expression.InG<T>(propertyName, values);
 61         //}
 62         //public static void InsensitiveLike(WhereBase where, string propertyName, object value)
 63         //{
 64         //    where.Instance = NHibernate.Expression.Expression.InsensitiveLike(propertyName, value);
 65         //}
 66         //public static void IsEmpty(WhereBase where, string propertyName)
 67         //{
 68         //    where.Instance = NHibernate.Expression.Expression.IsEmpty(propertyName);
 69         //}
 70         //public static void propertyName(WhereBase where, string propertyName)
 71         //{
 72         //    where.Instance = NHibernate.Expression.Expression.IsNotEmpty(propertyName);
 73         //}
 74         //public static void IsNotNull(WhereBase where, string propertyName)
 75         //{
 76         //    where.Instance = NHibernate.Expression.Expression.IsNotNull(propertyName);
 77         //}
 78         //public static void IsNull(WhereBase where, string propertyName)
 79         //{
 80         //    where.Instance = NHibernate.Expression.Expression.IsNull(propertyName);
 81         //}
 82         //public static void Le(WhereBase where, string propertyName, object value)
 83         //{
 84         //    where.Instance = NHibernate.Expression.Expression.Le(propertyName, value);
 85         //}
 86         //public static void LeProperty(WhereBase where, string propertyName, string otherPropertyName)
 87         //{
 88         //    where.Instance = NHibernate.Expression.Expression.LeProperty(propertyName, otherPropertyName);
 89         //}
 90         //public static void Like(WhereBase where, string propertyName, string value, NHibernate.Expression.MatchMode matchModes)
 91         //{
 92         //    where.Instance = NHibernate.Expression.Expression.Like(propertyName, value, matchModes);
 93         //}
 94 
 95         //public static void Lt(WhereBase where, string propertyName, object value)
 96         //{
 97         //    where.Instance = NHibernate.Expression.Expression.Lt(propertyName, value);
 98         //}
 99         //public static void LtProperty(WhereBase where, string propertyName, string otherPropertyName)
100         //{
101         //    where.Instance = NHibernate.Expression.Expression.LtProperty(propertyName, otherPropertyName);
102         //}
103         //public static void Not(WhereBase where)
104         //{
105         //    where.Instance = NHibernate.Expression.Expression.Not(where.Instance);
106         //}
107         //public static void NotEqProperty(WhereBase where, string propertyName, string otherPropertyName)
108         //{
109         //    where.Instance = NHibernate.Expression.Expression.NotEqProperty(propertyName, otherPropertyName);
110         //}
111         //public static void Or(WhereBase where, WhereBase whereA, WhereBase whereB)
112         //{
113         //    where.Instance = NHibernate.Expression.Expression.Or(whereA.Instance, whereB.Instance);
114         //}
115         //public static void Sql(WhereBase where, string sql)
116         //{
117         //    where.Instance = NHibernate.Expression.Expression.Sql(sql);
118         //}
119         #endregion
120     }
121 }

このような利点は,ORMがどのようなサードパーティフレームワークを用いているかにかかわらず,WhereBase静的メソッド(エージェントモード)を直接呼び出すことができることである.
WhereBaseはCastleの検索インタフェースICriterionを直接携帯しています.
RepositoryBaseでIWhereをCastleの検索オブジェクトに変換する方法があります
 1 #region     
 2         NHibernate.Expression.ICriterion[] IWhere2ICriterion(IWhere[] where)
 3         {
 4             if (where == null) {
 5                 return null;
 6             }
 7             NHibernate.Expression.ICriterion[] wheres = new NHibernate.Expression.ICriterion[where.Length];
 8             for (var i = 0; i < where.Length; i++)
 9             {
10                 wheres[i] = (where[i] as WhereBase).Instance;
11             }
12             return wheres;
13         }
14         #endregion

検索とソートのデカップリングを完璧に実現できます
倉庫ベースクラスには、次のような方法があります.
1 public IEnumerable<T> FindAll<T>(IWhere[] where) where T : IEntity
2         {
3             if (where == null) {
4                 return FindAll<T>();
5             }
6             return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(IWhere2ICriterion(where));
7         }

三、まとめ:
1:検索とソートのデカップリングは難題ではありません
2:実現した倉庫ベースクラスはIoC注入でインスタンス化でき、ORMを挿抜交換できる
3:定義された倉庫インタフェースと実装は、より良いデカップリングのために異なるクラスライブラリに置くことが望ましい.
四、後記:Repositoryは倉庫を実現する--Castle実現
 
1 namespace Yom.NFramework2_0.CastleExtend
2 {
3     public abstract class EntityBase : Castle.ActiveRecord.ActiveRecordBase, Yom.NFramework2_0.IEntity
4     {
5     }
6 }

ソリッドベースの結合
1 namespace Yom.NFramework2_0
2 {
3     public interface ISinglePrimaryKeyRepository : IRepository<string>
4     {
5     }
6 }

非組合せプライマリ・キー・ストレージの拡張
  1 namespace Yom.NFramework2_0.CastleExtend
  2 {
  3     public class CastleSinglePrimaryKeyRepository : ISinglePrimaryKeyRepository//, System.Configuration.IConfigurationSectionHandler
  4     {
  5         #region IRepository<string>   
  6 
  7         #region       
  8         public T FindBy<T>(string primaryKey) where T : IEntity
  9         {
 10             return Castle.ActiveRecord.ActiveRecordBase<T>.Find(primaryKey);
 11         }
 12 
 13         public IEnumerable<T> FindAll<T>() where T : IEntity
 14         {
 15             return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll();
 16         }
 17 
 18         public IEnumerable<T> FindAll<T>(IWhere[] where) where T : IEntity
 19         {
 20             if (where == null) {
 21                 return FindAll<T>();
 22             }
 23             return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(IWhere2ICriterion(where));
 24         }
 25 
 26         public IEnumerable<T> FindAll<T>(IWhere[] where, IOrder[] order) where T : IEntity
 27         {
 28             if (order == null)
 29             {
 30                 if (where == null)
 31                 {
 32                     return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll();
 33                 }
 34                 else
 35                 {
 36                     return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(IWhere2ICriterion(where));
 37                 }
 38             }
 39             else if (where == null)
 40             {
 41                 return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(order as NHibernate.Expression.Order[]);
 42             }
 43 
 44             return Castle.ActiveRecord.ActiveRecordBase<T>.FindAll(order as NHibernate.Expression.Order[], IWhere2ICriterion(where));
 45         }
 46 
 47         public IEnumerable<T> FindAll<T>(int pageIndex, int pageSize, IWhere[] where, IOrder[] order, out int count) where T : IEntity
 48         {
 49             if (where == null)
 50             {
 51                 count = Castle.ActiveRecord.ActiveRecordMediator.Count(typeof(T));
 52                 if (order == null) {
 53                     return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize);
 54 
 55                 }else{
 56                     return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize, order as NHibernate.Expression.Order[]);
 57                 }
 58             }
 59             else
 60             {
 61                 count = Castle.ActiveRecord.ActiveRecordMediator.Count(typeof(T), IWhere2ICriterion(where));
 62                 if (order == null) {
 63                     return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize, IWhere2ICriterion(where));
 64                 }
 65             }
 66             return Castle.ActiveRecord.ActiveRecordBase<T>.SlicedFindAll(pageIndex * pageSize, pageSize, order as NHibernate.Expression.Order[], IWhere2ICriterion(where));
 67         }
 68 
 69         public void Add<T>(T entity) where T : IEntity
 70         {
 71             using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
 72             {
 73                 (entity as Castle.ActiveRecord.ActiveRecordBase).CreateAndFlush();
 74                 tran.VoteCommit();
 75             }
 76         }
 77 
 78         public void Delete<T>(T entity) where T : IEntity
 79         {
 80             using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
 81             {
 82                 (entity as Castle.ActiveRecord.ActiveRecordBase).DeleteAndFlush();
 83                 tran.VoteCommit();
 84             }
 85         }
 86 
 87         public void DeleteAll<T>() where T : IEntity
 88         {
 89             using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
 90             {
 91                 Castle.ActiveRecord.ActiveRecordBase<T>.DeleteAll();
 92                 tran.VoteCommit();
 93             }
 94         }
 95 
 96         public void DeleteAll<T>(IWhere[] where) where T : IEntity
 97         {
 98             IEnumerable<T> entities;
 99             if (where == null)
100             {
101                 entities = this.FindAll<T>();
102             }
103             else
104             {
105                 entities = this.FindAll<T>(where);
106             }
107             if (entities != null)
108             {
109                 using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
110                 {
111                     foreach (T entity in entities) {
112                         this.Delete<T>(entity);
113                     }
114                     tran.VoteCommit();
115                 }
116             }
117         }
118         public void DeleteAll<T>(string where) where T : IEntity
119         {
120 
121             using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
122             {
123                 Castle.ActiveRecord.ActiveRecordBase<T>.DeleteAll(where);
124                 tran.VoteCommit();
125             }
126 
127         }
128         public void DeleteAll<T>(IEnumerable<string> pkValues) where T : IEntity
129         {
130             using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
131             {
132                 Castle.ActiveRecord.ActiveRecordBase<T>.DeleteAll(pkValues);
133                 tran.VoteCommit();
134             }
135         }
136 
137         public void Update<T>(T entity) where T : IEntity
138         {
139             using (Castle.ActiveRecord.TransactionScope tran = new Castle.ActiveRecord.TransactionScope())
140             {
141                 (entity as Castle.ActiveRecord.ActiveRecordBase).UpdateAndFlush();
142                 tran.VoteCommit();
143             }
144         }
145 
146         public bool Exists<T>(string primaryKey) where T : IEntity
147         {
148             return Castle.ActiveRecord.ActiveRecordBase<T>.Exists<string>(primaryKey);
149         }
150         #endregion
151         #region ado  sql
152         public int ExecuteSql(string sql, params System.Data.IDataParameter[] ps)
153         {
154             using (System.Data.IDbCommand cmd = Castle.ActiveRecord.ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(CastleSinglePrimaryKeyRepository)).Connection.CreateCommand())
155             {
156                 cmd.CommandText = sql;
157                 if (ps != null && ps.Length > 0)
158                 {
159                     foreach (System.Data.IDataParameter p in ps)
160                     {
161                         cmd.Parameters.Add(p);
162                     }
163                 }
164                 return cmd.ExecuteNonQuery();
165             }
166         }
167 
168         public object ExecuteScalar(string sql, params System.Data.IDataParameter[] ps)
169         {
170             using (System.Data.IDbCommand cmd = Castle.ActiveRecord.ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(CastleSinglePrimaryKeyRepository)).Connection.CreateCommand())
171             {
172                 cmd.CommandText = sql;
173                 if (ps != null && ps.Length > 0)
174                 {
175                     foreach (System.Data.IDataParameter p in ps)
176                     {
177                         cmd.Parameters.Add(p);
178                     }
179                 }
180                 return cmd.ExecuteScalar();
181             }
182         }
183 
184         public System.Data.DataTable ExecuteDataTable(string sql, params System.Data.IDataParameter[] ps)
185         {
186             using (System.Data.IDbCommand cmd = Castle.ActiveRecord.ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(CastleSinglePrimaryKeyRepository)).Connection.CreateCommand())
187             {
188                 cmd.CommandText = sql;
189                 if (ps != null && ps.Length > 0)
190                 {
191                     foreach (System.Data.IDataParameter p in ps)
192                     {
193                         cmd.Parameters.Add(p);
194                     }
195                 }
196                 System.Data.DataTable result = new System.Data.DataTable();
197                 result.Load(cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection));
198                 return result;
199             }
200         }
201         #endregion
202         #endregion
203         #region     
204         NHibernate.Expression.ICriterion[] IWhere2ICriterion(IWhere[] where)
205         {
206             if (where == null) {
207                 return null;
208             }
209             NHibernate.Expression.ICriterion[] wheres = new NHibernate.Expression.ICriterion[where.Length];
210             for (var i = 0; i < where.Length; i++)
211             {
212                 wheres[i] = (where[i] as WhereBase).Instance;
213             }
214             return wheres;
215         }
216         #endregion
217     }
218 }

 
 
Castle Ireposoitoryの実装
五、プロジェクト開発の階層
【Yom框架】漫谈个人框架的设计之二:新的IRepository接口+搜索和排序解耦(+基于Castle实现)_第1张图片