【Yomフレームワーク】個人フレームワークの設計の2つ:新しいIrepositoryインタフェース+検索とソートデカップリング(+Castleベースで実現)
67051 ワード
前編IrepositoryとIrepositoryの議論を経た【記事アドレス:http://www.cnblogs.com/yomho/p/3296759.html】
フレームワークを再構築する倉庫インタフェースとしてIrepositoryを選びました
一、インタフェース定義
新しいIrepositoryインタフェースは次のように設計されています.
ここでIEntityとIWhere及びIOrderの設計インタフェースは以下の通りである.
ICompositeKeyは結合プライマリ・キー・インタフェース
ICompositeKeyがIEquatableというインタフェースを継承するのはなぜですか?
IEquatableはstringのベースクラスであり、stringは継承できないクラスであるため、
したがって、stringと互換性を目的とし、処理によってstringクラスになり、通常の非組合せプライマリ・キーと互換性を得ることができる.
(本稿では,組合せプライマリ・キーの実現原理を述べず,組合せプライマリ・キー・インタフェースが組合せプライマリ・キーのデカップリングを実現する方法を示す)
二、接ぎ木Castleの検索とソートを実現する
多くの人は自分のIrepositoryインタフェースのソートと検索オブジェクトのデカップリングを知らない.
異なるORMでIrepositoryインタフェースを実現する時いつもどのように並べ替えて検索することを知りません
次に、Castleのソートと検索をIOrderとIWhereでデカップリングする方法を見てみましょう.
まずIOrder->NHibernate.Expression.オーダーの変身
これは簡単です.OrderBaseは一気にNHibernateになりました.Expression.Order
では、IWhereはIOrderのような変身を無事に果たすことができるのだろうか.
研究の結果、CastleはNHibernateであることが分かった.Expression.Expressionの静的メソッドクエリー・オブジェクトの作成
静的方法はNHibernateを返す.Expression.AbstraactCriterion抽象クラスまたはICriterionインタフェース
この抽象的なオブジェクトやインタフェースを継承して、変身を実现することができます!!!
しかし、もし本当にそうするならば、必然的に抽象的な方法が実現しなければならない.これは本当に下策だ.
それはNHibernateを直接実現したかどうか.Expression.AbstraactCriterion抽象クラスのクラスは?
どうせ見つからなかったのですが、Castleには必ずあります.もしこのようなクラスを見つけたら、IOrderのように接ぎ木を実現することができます.今は発見していません.彼の方法しか考えられません.
最後に私がWhereBaseに変身したのは:
このような利点は,ORMがどのようなサードパーティフレームワークを用いているかにかかわらず,WhereBase静的メソッド(エージェントモード)を直接呼び出すことができることである.
WhereBaseはCastleの検索インタフェースICriterionを直接携帯しています.
RepositoryBaseでIWhereをCastleの検索オブジェクトに変換する方法があります
検索とソートのデカップリングを完璧に実現できます
倉庫ベースクラスには、次のような方法があります.
三、まとめ:
1:検索とソートのデカップリングは難題ではありません
2:実現した倉庫ベースクラスはIoC注入でインスタンス化でき、ORMを挿抜交換できる
3:定義された倉庫インタフェースと実装は、より良いデカップリングのために異なるクラスライブラリに置くことが望ましい.
四、後記:Repositoryは倉庫を実現する--Castle実現
ソリッドベースの結合
非組合せプライマリ・キー・ストレージの拡張
Castle Ireposoitoryの実装
五、プロジェクト開発の階層
フレームワークを再構築する倉庫インタフェースとして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クラスになり、通常の非組合せプライマリ・キーと互換性を得ることができる.
(本稿では,組合せプライマリ・キーの実現原理を述べず,組合せプライマリ・キー・インタフェースが組合せプライマリ・キーのデカップリングを実現する方法を示す)
二、接ぎ木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の実装
五、プロジェクト開発の階層