`
zhmocean
  • 浏览: 195756 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用反射机制实现实体列表到DataTable的深层字段转换

阅读更多

  在《适配器模式在Web Service返回值中的应用》(http://blog.csdn.net/zhmnsw/archive/2007/07/23/1704235.aspx)一文中,我们使用到了IDataListAdapter接口来实现返回值数据表的转换操作,其中对于NHibernate返回的实体列表我们使用了TDlaEntityList类来进行转换。

但是,对于TDlaEntityList类型的实现,参考的一些代码只考虑到了基本数据类型字段的转换,而对于非系统定义的数据类型,或者具有组合性质的字段属性,该转换属于无效转换。比如一个Person和一个Address类型,为多对一关系,那么当Person包含一个Address类型的组合字段时,我们便无法将该字段简单的放入DataTable表中,而必须确定一个Address字段的别名字段。因此,本文描述了一种使用反射机制,填充实体列表组合字段值的方法。
一般情况下,对于基本数据类型字段,我们只需要使用PropertyInfo的GetValue方法及PropertyType属性等操作,就可以方便的将对象具有的各字段值一一读出,对于这类代码,网上有很多实现代码,在此不再赘述。
而对于我们上面提到的组合字段,由于无法预知字段嵌套的深度,比如对于多个类型连接的情况,我们可能会使用类似person.Address.Area.Areaname的语句形式来读取我们需要的映射字段值。那么,我们可不可以在使用TDlaEntityList类型进行“实体-数据记录”数据转换的时候,根据所设定的搜寻路径来自动寻找我们要转换的字段值呢?答案是肯定的,我们一步一步来。
对于TDlaEntityList类型我们应该先定义字段在DataTable中的别名、数据类型以及改别名值的搜寻路径,比如,我们设置一个组合字段的别名为BelongUserName、System.String类型,以及搜寻路径为BlongUser.UserName,那么在实体列表转换成DataTable型的时候会遵循以下算法:
1、 使用反射机制读取一个字段,并判断该字段是否为组合数据类型。
2、 如果不是,则返回该字段值,回到1。如果是,则继续。
3、 读取该组合字段的第一层字段名称(比如对于BlongUser.UserName,则返回BlongUser),并读取该层字段的值,并判断该值是否有下一级的组合字段。
4、 如果存在下一级组合字段,则去掉上层名称,回到步骤3,递归获取字段值。
5、 如果不存在下一级组合字段,且当前字段为基本数据类型,则返回该值。
6、 如果当前字段不是基本数据类型,则返回空(或者返回一个特定的快捷方式,此实现另文叙述)
注意:
      对于为空的组合字段值,直接返回空值(递归到哪层都会如此)
      如指定的搜寻路径无法找到,则返回空值
     对于指定的数据类型与实际字段数据类型的冲突,需要你自己负责
那么根据该算法,我们便可是根据指定的别名及搜寻路径,填充DataTable字段值。具体实现代码如下(.NET C#)
using System;
using System.Data;
using System.Collections;
using System.Reflection;
using QihangSoft.StringData;

namespace QihangSoft.Communication ...{


    
public class TDlaEntityList: QihangSoft.Communication.IDataListAdapter ...{
        
IDataList 成员#region IDataList 成员


        
public System.Data.DataColumnCollection ColumnList
        
...{
            
get
            
...{
                DataTable dt 
= ilistToTable();
                
return dt.Columns;
            }

        }


        
public System.Data.DataRowCollection RecordList
        
...{
            
get
            
...{
                DataTable dt 
= ilistToTable();
                
return dt.Rows;
            }

        }

        
public string ListName ...{
            
get ...{
                
return "";
            }

        }


        
public DataTable AsDataTable
        
...{
            
get
            
...{
                
return ilistToTable();
            }

        }


        
#endregion



        
public TDlaEntityList( IList entityList) ...{
            
//初始化各列表
            FEntityList = entityList;
            FRecursionPropertyList 
= new TStrList();
            FRecursionPropertyTypeList 
= new ArrayList();
        }


        
private IList FEntityList;
        
private TStrList FRecursionPropertyList; //组合属性字段名称及搜寻路径列表
        private ArrayList FRecursionPropertyTypeList; //组合字段属性类型列表

        
/**//// <summary>
        
/// 实体列表转换成DataTable
        
/// </summary>
        
/// <returns></returns>
        private DataTable ilistToTable()
        
...{
            DataTable dt 
= new DataTable();
            TStrList noSysType 
= new TStrList();
            
if ((FEntityList != null)&&(FEntityList.Count >0))
            
...{    
                
//获取反射属性信息
                System.Reflection.PropertyInfo[] columnList = getObjectPropertyInfo(FEntityList[0]);

                
//遍历属性列表,存入DataTable
                foreach(System.Reflection.PropertyInfo column in columnList)
                
...{
                
                    
//获取非系统类型字段列表,以便返回实体快捷方式
                    System.Type typeimp = System.Type.GetType(column.PropertyType.ToString());
                    
if (typeimp == null)
                    
...{
                        noSysType.addNew(column.Name, column.Name);

                        
//dt.Columns.Add(column.Name, System.Type.GetType("System.String"));            
                    }

                    
else
                    
...{
                        dt.Columns.Add(column.Name, typeimp);
                    }

                }


                
//载入递归字段类型
                for    (int a=0; a<FRecursionPropertyList.count; a++)
                
...{
                    dt.Columns.Add(FRecursionPropertyList.getName(a), (System.Type)(FRecursionPropertyTypeList[a]));
                }


                
//遍历整个IList,获取数据
                for(int i=0; i<FEntityList.Count; i++)
                
...{
                    IList TempList 
= new ArrayList();
                    
//将IList中一条记录的有效属性字段写入ArrayList
                    foreach (System.Reflection.PropertyInfo pi in columnList)
                    
...{
                        
//未在排除列表中出现的字段为有效属性字段
                        if (noSysType.valueByName(pi.Name) == TStrDefine.NULL_STR)
                        
...{
                            
object oo = pi.GetValue(FEntityList[i], null);
                            TempList.Add(oo);
                        }

                    }

                
                    
object[] itm=new object[TempList.Count + FRecursionPropertyList.count];
                    
//遍历ArrayList向object[]里放数据

                    
for (int j = 0; j < TempList.Count; j++)
                    
...{
                        itm.SetValue(TempList[j], j);
                    }

                    
//遍历递归数据
                    for(int k =0; k<FRecursionPropertyList.count; k++)
                    
...{
                        
object obj = getPropertyValue(FEntityList[i], FRecursionPropertyList.getValue(k));
                        itm.SetValue(obj, TempList.Count
+k);
                    }
        

                    
//将object[]
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics