MySoft.Data发现系列一:实体的解耦

  自老毛开始发布他的MySoft.Data系列组件,也陆续开始写Mysoft.Data使用系列的文章,我也尝试着写一点自己在研究和使用MySoft.Data过程中的一些心得。

  

  本章介绍Mysoft.Data在作为一个ORM组件应用在系统中时,如何把MySoft.Data生成的实体转换成“干净”的实体,以实现系统和ORM之间的解耦。

  大家都知道,一般ORM组件会有他们自己的特定的实体,例如EF的实体,或者其他ORM组件的实体,要么通过Attribute标记,要么xml文档配置,总而言之就是要把实体的结构跟数据表结构联系起来,MySoft.Data也不例外,大家来看它生成的实体:

ExpandedBlockStart.gif 代码
  1  ///   <summary>
  2       ///  表名:Category 主键列:CategoryID
  3       ///   </summary>
  4      [SerializableAttribute()]
  5       public   partial   class  Category : Entity
  6      {
  7 
  8           protected  Int32 _CategoryID;
  9 
 10           protected  String _Name;
 11 
 12           protected  Int32 _UserID;
 13 
 14           public  Int32 CategoryID
 15          {
 16               get
 17              {
 18                   return   this ._CategoryID;
 19              }
 20               set
 21              {
 22                   this .OnPropertyValueChange(_.CategoryID, _CategoryID, value);
 23                   this ._CategoryID  =  value;
 24              }
 25          }
 26 
 27           public  String Name
 28          {
 29               get
 30              {
 31                   return   this ._Name;
 32              }
 33               set
 34              {
 35                   this .OnPropertyValueChange(_.Name, _Name, value);
 36                   this ._Name  =  value;
 37              }
 38          }
 39 
 40           public  Int32 UserID
 41          {
 42               get
 43              {
 44                   return   this ._UserID;
 45              }
 46               set
 47              {
 48                   this .OnPropertyValueChange(_.UserID, _UserID, value);
 49                   this ._UserID  =  value;
 50              }
 51          }
 52 
 53           ///   <summary>
 54           ///  获取实体对应的表名
 55           ///   </summary>
 56           protected   override  Table GetTable()
 57          {
 58               return   new  Table < Category > ( " Category " );
 59          }
 60 
 61           ///   <summary>
 62           ///  获取实体中的标识列
 63           ///   </summary>
 64           protected   override  Field GetIdentityField()
 65          {
 66               return  _.CategoryID;
 67          }
 68 
 69           ///   <summary>
 70           ///  获取实体中的主键列
 71           ///   </summary>
 72           protected   override  Field[] GetPrimaryKeyFields()
 73          {
 74               return   new  Field[] {
 75                          _.CategoryID};
 76          }
 77 
 78           ///   <summary>
 79           ///  获取列信息
 80           ///   </summary>
 81           protected   override  Field[] GetFields()
 82          {
 83               return   new  Field[] {
 84                          _.CategoryID,
 85                          _.Name,
 86                          _.UserID};
 87          }
 88 
 89           ///   <summary>
 90           ///  获取列数据
 91           ///   </summary>
 92           protected   override   object [] GetValues()
 93          {
 94               return   new   object [] {
 95                           this ._CategoryID,
 96                           this ._Name,
 97                           this ._UserID};
 98          }
 99 
100           ///   <summary>
101           ///  给当前实体赋值
102           ///   </summary>
103           protected   override   void  SetValues(IRowReader reader)
104          {
105               if  (( false   ==  reader.IsDBNull(_.CategoryID)))
106              {
107                   this ._CategoryID  =  reader.GetInt32(_.CategoryID);
108              }
109               if  (( false   ==  reader.IsDBNull(_.Name)))
110              {
111                   this ._Name  =  reader.GetString(_.Name);
112              }
113               if  (( false   ==  reader.IsDBNull(_.UserID)))
114              {
115                   this ._UserID  =  reader.GetInt32(_.UserID);
116              }
117          }
118 
119           public   override   int  GetHashCode()
120          {
121               return   base .GetHashCode();
122          }
123 
124           public   override   bool  Equals( object  obj)
125          {
126               if  ((obj  ==   null ))
127              {
128                   return   false ;
129              }
130               if  (( false   ==   typeof (Category).IsAssignableFrom(obj.GetType())))
131              {
132                   return   false ;
133              }
134               if  (((( object )( this ))  ==  (( object )(obj))))
135              {
136                   return   true ;
137              }
138               return   false ;
139          }
140 
141           public   class  _
142          {
143 
144               ///   <summary>
145               ///  表示选择所有列,与*等同
146               ///   </summary>
147               public   static  AllField All  =   new  AllField < Category > ();
148 
149               ///   <summary>
150               ///  字段名:CategoryID - 数据类型:Int32
151               ///   </summary>
152               public   static  Field CategoryID  =   new  Field < Category > ( " CategoryID " );
153 
154               ///   <summary>
155               ///  字段名:Name - 数据类型:String
156               ///   </summary>
157               public   static  Field Name  =   new  Field < Category > ( " Name " );
158 
159               ///   <summary>
160               ///  字段名:UserID - 数据类型:Int32
161               ///   </summary>
162               public   static  Field UserID  =   new  Field < Category > ( " UserID " );
163          }
164      }

 我们来看看其实Category实体无非也就那么几个属性

1  public   interface  Category : IEntity
2      {
3          [PrimaryKey]
4           int  CategoryID {  get ; }
5           string  Name {  get set ; }
6           int  UserID {  get set ; }
7      }

如果使用MySoft.Data的实体,那就意味着你离不开MySoft.Data框架。

而实际项目中我们一定不会这么做(简单的项目就不说了),那么如何如何使用简单的“失血”实体和这个ORM中的实体项目转换呢,其实MySoft.Data里已经提供了灰常简单的方法,我们先来看看MySoft.Data里定义的接口:

ExpandedBlockStart.gif 代码
 1  ///   <summary>
 2       ///  列表转换
 3       ///   </summary>
 4       public   interface  IListConvert < T >
 5      {
 6           ///   <summary>
 7           ///  返回另一类型的列表
 8           ///   </summary>
 9           ///   <typeparam name="TOutput"></typeparam>
10           ///   <returns></returns>
11          ISourceList < TOutput >  ConvertTo < TOutput > ();
12 
13           ///   <summary>
14           ///  返回另一类型的列表(输出为接口)
15           ///   </summary>
16           ///   <typeparam name="TOutput"></typeparam>
17           ///   <typeparam name="IOutput"></typeparam>
18           ///   <returns></returns>
19          ISourceList < IOutput >  ConvertTo < TOutput, IOutput > ();
20 
21           ///   <summary>
22           ///  将当前类型转成另一种类型
23           ///   </summary>
24           ///   <typeparam name="TOutput"></typeparam>
25           ///   <param name="converter"></param>
26           ///   <returns></returns>
27          ISourceList < TOutput >  ConvertAll < TOutput > (Converter < T, TOutput >  converter);
28      }

我们再来看看,它的继承关系

ExpandedBlockStart.gif 代码
 1  ///   <summary>
 2       ///  数据源接口
 3       ///   </summary>
 4       public   interface  ISourceList < T >  : IListConvert < T > , IArrayList < T >
 5      {
 6           ///   <summary>
 7           ///  转换成SourceTable
 8           ///   </summary>
 9           ///   <returns></returns>
10          ISourceTable ToTable();
11 
12           ///   <summary>
13           ///  返回MemoryFrom
14           ///   </summary>
15           ///   <returns></returns>
16          MemoryFrom < T >  ToMemory();
17 
18           ///   <summary>
19           ///  添加一个实体
20           ///   </summary>
21           ///   <param name="item"></param>
22           ///   <returns></returns>
23           new  ISourceList < T >  Add(T item);
24 
25           ///   <summary>
26           ///  添加一个实体
27           ///   </summary>
28           ///   <param name="item"></param>
29           ///   <returns></returns>
30          ISourceList < T >  AddRange(IEnumerable < T >  collection);
31 
32           #region  字典操作
33 
34           ///   <summary>
35           ///  返回字典
36           ///   </summary>
37           ///   <typeparam name="TResult"></typeparam>
38           ///   <param name="groupName"></param>
39           ///   <returns></returns>
40          IDictionary < TResult, IList < T >>  ToGroupList < TResult > ( string  groupName);
41 
42           ///   <summary>
43           ///  返回字典
44           ///   </summary>
45           ///   <typeparam name="TResult"></typeparam>
46           ///   <param name="groupField"></param>
47           ///   <returns></returns>
48          IDictionary < TResult, IList < T >>  ToGroupList < TResult > (Field groupField);
49 
50           #endregion
51      }

ISourceList<T>继承自IListConvert<T>和IArrayList<T>,IArrayList<T>是啥,IArrayList<T>是一个实现了IList<T>的东东,因此,实现ISourceList<T>,一定会实现IList<T>,我们就可以使用可爱的IList<T>了。

但实际上,MySoft.Data里的SourceList实现了ISourceList,不仅如此,SourceList还(间接)实现了List<T>,大家看它的继承关系

ExpandedBlockStart.gif 代码
  1  ///   <summary>
  2       ///  数组列表
  3       ///   </summary>
  4       ///   <typeparam name="T"></typeparam>
  5       public   class  SourceList < T >  : ArrayList < T > , ISourceList < T >
  6      {
  7           public  SourceList() { }
  8 
  9           ///   <summary>
 10           ///  实例化SourceList
 11           ///   </summary>
 12           ///   <param name="list"></param>
 13           public  SourceList(IList < T >  list)
 14              :  base (list)
 15          { }
 16 
 17           #region  IArrayList<T> 成员
 18 
 19           ///   <summary>
 20           ///  转换成SourceTable
 21           ///   </summary>
 22           ///   <returns></returns>
 23           public  ISourceTable ToTable()
 24          {
 25               return   new  SourceTable( this .GetDataTable());
 26          }
 27 
 28           ///   <summary>
 29           ///  返回MemoryFrom
 30           ///   </summary>
 31           ///   <returns></returns>
 32           public  MemoryFrom < T >  ToMemory()
 33          {
 34               return   new  MemoryFrom < T > ( this .GetDataTable());
 35          }
 36 
 37           ///   <summary>
 38           ///  返回另一类型的列表(用于实体的解耦))
 39           ///   </summary>
 40           ///   <typeparam name="TOutput"></typeparam>
 41           ///   <returns></returns>
 42           public  ISourceList < TOutput >  ConvertTo < TOutput > ()
 43          {
 44               return   this .ConvertAll < TOutput > (p  =>  DataUtils.ConvertType < T, TOutput > (p));
 45          }
 46 
 47           ///   <summary>
 48           ///  将当前类型转成另一种类型
 49           ///   </summary>
 50           ///   <typeparam name="TOutput"></typeparam>
 51           ///   <param name="converter"></param>
 52           ///   <returns></returns>
 53           public   new  ISourceList < TOutput >  ConvertAll < TOutput > (Converter < T, TOutput >  converter)
 54          {
 55              IList < TOutput >  list  =   base .ConvertAll < TOutput > (converter);
 56               return   new  SourceList < TOutput > (list);
 57          }
 58 
 59           ///   <summary>
 60           ///  添加一个实体
 61           ///   </summary>
 62           ///   <param name="item"></param>
 63           ///   <returns></returns>
 64           public   new  ISourceList < T >  Add(T item)
 65          {
 66               base .Add(item);
 67               return   this ;
 68          }
 69 
 70           ///   <summary>
 71           ///  添加一个实体
 72           ///   </summary>
 73           ///   <param name="item"></param>
 74           ///   <returns></returns>
 75           public   new  ISourceList < T >  AddRange(IEnumerable < T >  collection)
 76          {
 77               base .AddRange(collection);
 78               return   this ;
 79          }
 80 
 81           ///   <summary>
 82           ///  返回另一类型的列表(输入为类、输出为接口,用于实体的解耦)
 83           ///   </summary>
 84           ///   <typeparam name="TOutput"></typeparam>
 85           ///   <typeparam name="IOutput"></typeparam>
 86           ///   <returns></returns>
 87           public  ISourceList < IOutput >  ConvertTo < TOutput, IOutput > ()
 88          {
 89               if  ( ! typeof (TOutput).IsClass)
 90              {
 91                   throw   new  MySoftException( " TOutput必须是Class类型! " );
 92              }
 93 
 94               if  ( ! typeof (IOutput).IsInterface)
 95              {
 96                   throw   new  MySoftException( " IOutput必须是Interface类型! " );
 97              }
 98 
 99               // 进行两次转换后返回
100               return  ConvertTo < TOutput > ().ConvertTo < IOutput > ();
101          }
102 
103           #region  字典操作
104 
105           ///   <summary>
106           ///  返回字典
107           ///   </summary>
108           ///   <typeparam name="TResult"></typeparam>
109           ///   <param name="groupField"></param>
110           ///   <returns></returns>
111           public  IDictionary < TResult, IList < T >>  ToGroupList < TResult > (Field groupField)
112          {
113               return  ToGroupList < TResult > (groupField.PropertyName);
114          }
115 
116           ///   <summary>
117           ///  返回字典
118           ///   </summary>
119           ///   <typeparam name="TResult"></typeparam>
120           ///   <param name="groupName"></param>
121           ///   <returns></returns>
122           public  IDictionary < TResult, IList < T >>  ToGroupList < TResult > ( string  groupName)
123          {
124              IDictionary < TResult, IList < T >>  group  =   new  Dictionary < TResult, IList < T >> ();
125               if  ( this .Count  ==   0 return  group;
126 
127               foreach  (T t  in   this )
128              {
129                   object  obj  =  DataUtils.GetPropertyValue(t, groupName);
130                  TResult value  =  DataUtils.ConvertValue < TResult > (obj);
131                   if  ( ! group.ContainsKey(value))
132                  {
133                      group.Add(value,  new  SourceList < T > ());
134                  }
135                  group[value].Add(t);
136              }
137 
138               return  group;
139          }
140 
141           #endregion
142 
143           ///   <summary>
144           ///   转换成DataTable
145           ///   </summary>
146           ///   <returns></returns>
147           private  DataTable GetDataTable()
148          {
149               #region  对list进行转换
150 
151              DataTable dt  =   new  DataTable();
152              dt.TableName  =   typeof (T).Name;
153 
154              T obj  =  DataUtils.CreateInstance < T > ();
155              PropertyInfo[] plist  =  obj.GetType().GetProperties();
156               foreach  (PropertyInfo p  in  plist)
157              {
158                  Type propertyType  =  p.PropertyType;
159                   if  ( ! CanUseType(propertyType))  continue // shallow only
160 
161                   // nullables must use underlying types
162                   if  (propertyType.IsGenericType  &&  propertyType.GetGenericTypeDefinition()  ==   typeof (Nullable <> ))
163                      propertyType  =  Nullable.GetUnderlyingType(propertyType);
164                   // enums also need special treatment
165                   if  (propertyType.IsEnum)
166                      propertyType  =  Enum.GetUnderlyingType(propertyType);  // probably Int32
167 
168                  dt.Columns.Add(p.Name, propertyType);
169              }
170 
171               if  ( this .Count  ==   0 return  dt;
172 
173               foreach  (T t  in   this )
174              {
175                  DataRow dtRow  =  dt.NewRow();
176                   foreach  (PropertyInfo p  in  plist)
177                  {
178                       object  value  =  DataUtils.GetPropertyValue(t, p.Name);
179                      dtRow[p.Name]  =  value  ==   null   ?  DBNull.Value : value;
180                  }
181                  dt.Rows.Add(dtRow);
182              }
183 
184               #endregion
185 
186               return  dt;
187          }
188 
189           private   static   bool  CanUseType(Type propertyType)
190          {
191               // only strings and value types
192               if  (propertyType.IsArray)  return   false ;
193               if  ( ! propertyType.IsValueType  &&  propertyType  !=   typeof ( string ))  return   false ;
194               return   true ;
195          }
196 
197           #endregion
198      }

看来,我们不用担心兼容问题了,它就是List。

说了这么多废话,怎么使用它转成干净的实体呢??

 

项目中,我们可以把实体定义成接口,或者直接实体也行,怎么用,来看看这几个方法,这是今天我在ben的开源blog,xpress看到的

ExpandedBlockStart.gif 代码
 1    ///   <summary>
 2           ///  获取评论列表
 3           ///   </summary>
 4           ///   <param name="status"> 状态 </param>
 5           ///   <param name="pageNumber"> 页码 </param>
 6           ///   <param name="pageSize"> 分页大小 </param>
 7           ///   <returns></returns>
 8           public  IList < IComments >  GetList(CommentStatus status,  int  pageNumber,  int  pageSize)
 9          {
10               return  repository.GetSession().From < Comments > ()
11                      .Where(Comments._.CommentStatus  ==  status)
12                      .OrderBy(Comments._.CommentTimeGMT.Desc)
13                      .GetPage(pageSize)
14                      .ToList(pageNumber).ConvertTo < CommentsModel, IComments > (); // 这里转化了成了SourceList<IComments>,而由于SourceList实现了IList<T>,因此兼容IList<IComments>了
15          }
16 
17 
18  // 再来看这几个个扩展方法
19 
20  ///   <summary>
21           ///  转换成实体
22           ///   </summary>
23           ///   <typeparam name="TEntity"></typeparam>
24           ///   <param name="entity"></param>
25           ///   <returns></returns>
26           public   static  TEntity ToEntity < TEntity > ( this  DsJian.Interface.Model.IEntity entity)
27               where  TEntity : MySoft.Data.Entity
28          {
29               return   new  MySoft.Data.SourceList < DsJian.Interface.Model.IEntity > (entity).ConvertTo < TEntity > ()[ 0 ];
30          }
31 
32           ///   <summary>
33           ///  转换成实体
34           ///   </summary>
35           ///   <typeparam name="TEntity"></typeparam>
36           ///   <param name="entity"></param>
37           ///   <returns></returns>
38           public   static  TEntity ToEntity < TEntity > ( this  MySoft.Data.Entity entity)
39          {
40               return   new  MySoft.Data.SourceList < MySoft.Data.Entity > (entity).ConvertTo < TEntity > ()[ 0 ];
41          }
42 
43           ///   <summary>
44           ///  转换成接口
45           ///   </summary>
46           ///   <typeparam name="TEntity"></typeparam>
47           ///   <typeparam name="IEntity"></typeparam>
48           ///   <param name="entity"></param>
49           ///   <returns></returns>
50           public   static  IEntity ToIEntity < TEntity, IEntity > ( this  MySoft.Data.Entity entity)
51               where  IEntity : DsJian.Interface.Model.IEntity
52          {
53               return   new  MySoft.Data.SourceList < MySoft.Data.Entity > (entity).ConvertTo < TEntity, IEntity > ()[ 0 ];
54          }

我不用说,大家也该知道怎么用了。

OK,我是个不怎么会写东西的人,文章中可能有什么胡言乱语的云云,请大家爱护环境,留住你们手中紧攥的臭鸡蛋,谢谢!

 

 

 

 

 

转载于:https://www.cnblogs.com/uxspy/archive/2010/03/16/1687474.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值