在《适配器模式在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 成员
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[]的内容放入DataTable
dt.LoadDataRow(itm, true);
}
}
return dt;
}
/// <summary>
/// 设置递归属性字段
/// </summary>
/// <param name=”columnName”>属性别名</param>
/// <param name=”recursionName”>递归属性名称</param>
/// <param name=”recursionType”>属性数据类型</param>
public void setRecursionField(string columnName, string recursionName, System.Type recursionType)
{
FRecursionPropertyList.addNew(columnName, recursionName);
FRecursionPropertyTypeList.Add(recursionType);
}
/// <summary>
/// 获取实体类型的属性列表
/// </summary>
/// <param name=”obj”>传入的实体</param>
/// <returns></returns>
private System.Reflection.PropertyInfo[] getObjectPropertyInfo(object obj)
{
if (obj != null)
{
return obj.GetType().GetProperties();
}
else
{
return null;
}
}
/// <summary>
/// 递归函数,获取属性值
/// </summary>
/// <param name=”obj”>传入的实体对象</param>
/// <param name=”propertyName”>属性名称</param>
/// <returns></returns>
private object getPropertyValue(object obj, string propertyName)
{
//取得propertyName第一段属性字符串
string topPropertyName = getTopPropertyName(propertyName);
if (obj != null)
{
System.Reflection.PropertyInfo pi = obj.GetType().GetProperty(topPropertyName);
string subPropertyName = deleteTopPropertyName(propertyName);
if (!“”.Equals(subPropertyName))
{
//如果还有下一级属性名称,则递归获取字段值
return getPropertyValue(pi.GetValue(obj, null), subPropertyName);
}
else
{
//如果没有下一级属性名称,则返回指定字段值
return pi.GetValue(obj, null);
}
}
else
{
return null;
}
}
/// <summary>
/// 获取属性名称顶部名称值,例如:BlongUser.UserName,则返回BlongUser
/// </summary>
/// <param name=”propertyName”>传入的属性名称</param>
/// <returns></returns>
private string getTopPropertyName(string propertyName)
{
//搜索点号“.”的位置
if (! “”.Equals(propertyName))
{
string[] strList = propertyName.Split(‘.‘);
if (strList.Length >0)
{
return strList[0];
}
else
{
return “”;
}
}
else
{
return “”;
}
}
/// <summary>
/// 删除属性名称顶部名称值,例如:BlongUser.UserName,则返回UserName
/// </summary>
/// <param name=”propertyName”>传入的属性名称</param>
/// <returns></returns>
private string deleteTopPropertyName(string propertyName)
{
if (! “”.Equals(propertyName))
{
int dotPos = propertyName.IndexOf(‘.‘);
if (dotPos >-1)
{
return propertyName.Remove(0, dotPos+1);
}
else
{
return “”;
}
}
else
{
return “”;
}
}
}
}
using System.Data;
using System.Collections;
using System.Reflection;
using QihangSoft.StringData;
namespace QihangSoft.Communication {
public class TDlaEntityList: QihangSoft.Communication.IDataListAdapter {
IDataList 成员
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[]的内容放入DataTable
dt.LoadDataRow(itm, true);
}
}
return dt;
}
/// <summary>
/// 设置递归属性字段
/// </summary>
/// <param name=”columnName”>属性别名</param>
/// <param name=”recursionName”>递归属性名称</param>
/// <param name=”recursionType”>属性数据类型</param>
public void setRecursionField(string columnName, string recursionName, System.Type recursionType)
{
FRecursionPropertyList.addNew(columnName, recursionName);
FRecursionPropertyTypeList.Add(recursionType);
}
/// <summary>
/// 获取实体类型的属性列表
/// </summary>
/// <param name=”obj”>传入的实体</param>
/// <returns></returns>
private System.Reflection.PropertyInfo[] getObjectPropertyInfo(object obj)
{
if (obj != null)
{
return obj.GetType().GetProperties();
}
else
{
return null;
}
}
/// <summary>
/// 递归函数,获取属性值
/// </summary>
/// <param name=”obj”>传入的实体对象</param>
/// <param name=”propertyName”>属性名称</param>
/// <returns></returns>
private object getPropertyValue(object obj, string propertyName)
{
//取得propertyName第一段属性字符串
string topPropertyName = getTopPropertyName(propertyName);
if (obj != null)
{
System.Reflection.PropertyInfo pi = obj.GetType().GetProperty(topPropertyName);
string subPropertyName = deleteTopPropertyName(propertyName);
if (!“”.Equals(subPropertyName))
{
//如果还有下一级属性名称,则递归获取字段值
return getPropertyValue(pi.GetValue(obj, null), subPropertyName);
}
else
{
//如果没有下一级属性名称,则返回指定字段值
return pi.GetValue(obj, null);
}
}
else
{
return null;
}
}
/// <summary>
/// 获取属性名称顶部名称值,例如:BlongUser.UserName,则返回BlongUser
/// </summary>
/// <param name=”propertyName”>传入的属性名称</param>
/// <returns></returns>
private string getTopPropertyName(string propertyName)
{
//搜索点号“.”的位置
if (! “”.Equals(propertyName))
{
string[] strList = propertyName.Split(‘.‘);
if (strList.Length >0)
{
return strList[0];
}
else
{
return “”;
}
}
else
{
return “”;
}
}
/// <summary>
/// 删除属性名称顶部名称值,例如:BlongUser.UserName,则返回UserName
/// </summary>
/// <param name=”propertyName”>传入的属性名称</param>
/// <returns></returns>
private string deleteTopPropertyName(string propertyName)
{
if (! “”.Equals(propertyName))
{
int dotPos = propertyName.IndexOf(‘.‘);
if (dotPos >-1)
{
return propertyName.Remove(0, dotPos+1);
}
else
{
return “”;
}
}
else
{
return “”;
}
}
}
}