在我们的项目中,用到了很多对象数组。需要把对象数组绑定到DataGrid上,但目前好像不能直接绑定。就只有转换为DataTable。好不容易在网上找到了别人写的一个类。但和我们的需要比还是差了一点。他只能把对象的属性转换为DataTable的列。但我们的对象数组都是WebServices自动生成的。也就是没有属性,只有Public的字段。所以我就在别人的基础上写了一个即可以转换属性又可以转换字段的类。不过必须要Public的哦。在加上我们的项目中经常在对象里还有对象,所以又支持了对象中包含对象的对象数组。具体代码如下:
欢迎各位网友改进,也希望大家改进后能贡献一下
using System;
using System.Data;
using System.Collections;
using System.Reflection;
namespace sms.Components
{
/// <summary>
/// ObjectArrayToDataTable 的摘要说明。
/// </summary>
public class ObjectArrayToDataTable
{
#region 构造函数
public ObjectArrayToDataTable()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
#endregion
#region 属性设置
private bool _ColumnFromProperty = true;
/// <summary>
/// DataTable列是否根据对象的属性生成;默认为True,如果为False则由对象的字段生成
/// </summary>
public bool ColumnFromProperty
{
get{return _ColumnFromProperty;}
set{_ColumnFromProperty=value;}
}
private string _PointString = ".";
/// <summary>
/// 点号的替换符号
/// </summary>
public string PointString
{
get{return _PointString;}
set{_PointString = value;}
}
#endregion
#region 公共方法
/// <summary>
/// 对象数组转换为DataTable
/// </summary>
/// <param name="objArry">对象数组</param>
/// <returns></returns>
public DataTable ArrayToDataTable(object[] objArry)
{
if(objArry.Length <= 0)
{
return null;
}
Type objType = objArry[0].GetType();
DataTable dt = CreateDataTable(objType);
dt = FillDataTable(dt, objArry);
return dt;
}
#endregion
#region 私有方法
/// <summary>
/// 创建DataTable
/// </summary>
/// <param name="objType"></param>
/// <returns></returns>
private DataTable CreateDataTable(Type objType)
{
DataTable dt = new DataTable();
ArrayList[] myList;
if(this.ColumnFromProperty)
{
myList = GetPropertiesInfo(objType, "");
}
else
{
myList = GetFieldsInfo(objType, "");
}
for(int i=0; i<myList[0].Count; i++)
{
DataColumn dColumn = new DataColumn(myList[0][i].ToString(), System.Type.GetType(myList[1][i].ToString()));
dt.Columns.Add(dColumn);
}
return dt;
}
private DataTable FillDataTable(DataTable dt, object[] objArry)
{
DataColumnCollection dtColumns = dt.Columns;
Type objType = objArry[0].GetType();
foreach (object obj in objArry)
{
DataRow dRow = dt.NewRow();
for (int i = 0; i < dtColumns.Count; i++)
{
if(this.ColumnFromProperty)
{
dRow[i] = GetPropertyByPath(dtColumns[i].ColumnName, obj);
}
else
{
dRow[i] = GetFieldByPath(dtColumns[i].ColumnName, obj);
}
}
dt.Rows.Add(dRow);
}
return dt;
}
/// <summary>
/// 获取对象的字段信息
/// </summary>
/// <param name="myType">对象的类型</param>
/// <param name="UpName">上级名称</param>
/// <returns></returns>
private ArrayList[] GetFieldsInfo(Type myType, string UpName)
{
ArrayList[] myList = new ArrayList[2];
myList[0] = new ArrayList();
myList[1] = new ArrayList();
FieldInfo[] myFieldInfo = myType.GetFields();
string strType = "";
string strName = "";
foreach (FieldInfo myField in myFieldInfo)
{
strName = (UpName == "")?myField.Name:UpName + this.PointString + myField.Name;
strType = myField.FieldType.ToString();
if(strType.Length > 2 && strType.Substring(strType.Length - 2, 2) != "[]")
{
if(strType.Length > 6 && strType.Substring(0, 6) == "System")
{
myList[0].Add(strName);
myList[1].Add(myField.FieldType.ToString());
}
else
{
ArrayList[] aryOther = GetFieldsInfo(myField.FieldType, strName);
for(int i=0; i<aryOther[0].Count; i++)
{
myList[0].Add(aryOther[0][i]);
myList[1].Add(aryOther[1][i]);
}
}
}
}
return myList;
}
/// <summary>
/// 获取对象的属性信息
/// </summary>
/// <param name="myType">对象的类型</param>
/// <param name="UpName">上级名称</param>
/// <returns></returns>
private ArrayList[] GetPropertiesInfo(Type myType, string UpName)
{
ArrayList[] myList = new ArrayList[2];
myList[0] = new ArrayList();
myList[1] = new ArrayList();
PropertyInfo[] myPropertyInfo = myType.GetProperties();
string strType = "";
string strName = "";
foreach (PropertyInfo myProperty in myPropertyInfo)
{
strName = (UpName == "")?myProperty.Name:UpName + this.PointString + myProperty.Name;
strType = myProperty.PropertyType.ToString();
if(strType.Length > 2 && strType.Substring(strType.Length - 2, 2) != "[]")
{
if(strType.Length > 6 && strType.Substring(0, 6) == "System")
{
myList[0].Add(strName);
myList[1].Add(strType);
}
else
{
ArrayList[] aryOther = GetPropertiesInfo(myProperty.PropertyType, strName);
for(int i=0; i<aryOther[0].Count; i++)
{
myList[0].Add(aryOther[0][i]);
myList[1].Add(aryOther[1][i]);
}
}
}
}
return myList;
}
private object GetFieldByPath(string strPath, object obj)
{
object objRet;
string[] aryPaths;
string strOtherPath = "";
Type objType = obj.GetType();
if(strPath.IndexOf(this.PointString) < 0)
{
objRet = objType.InvokeMember(strPath, BindingFlags.GetField, null, obj, null);
}
else
{
aryPaths = SplitPage(strPath, this.PointString);
for(int i=1; i<aryPaths.Length; i++)
{
if(strOtherPath!=""){strOtherPath += this.PointString;}
strOtherPath += aryPaths[i];
}
object objTemp = objType.InvokeMember(aryPaths[0], BindingFlags.GetField, null, obj, null);
objRet = GetFieldByPath(strOtherPath, objTemp);
}
return objRet;
}
private object GetPropertyByPath(string strPath, object obj)
{
object objRet;
string[] aryPaths;
string strOtherPath = "";
Type objType = obj.GetType();
if(strPath.IndexOf(this.PointString) < 0)
{
objRet = objType.InvokeMember(strPath, BindingFlags.GetProperty, null, obj, null);
}
else
{
aryPaths = SplitPage(strPath, this.PointString);
for(int i=1; i<aryPaths.Length; i++)
{
if(strOtherPath!=""){strOtherPath += this.PointString;}
strOtherPath += aryPaths[i];
}
object objTemp = objType.InvokeMember(aryPaths[0], BindingFlags.GetProperty, null, obj, null);
objRet = GetFieldByPath(strOtherPath, objTemp);
}
return objRet;
}
/// <summary>
/// 根据指定的标记符,分隔字符串,并返回字符数组
/// </summary>
/// <param name="source">要分隔的字符串</param>
/// <param name="split">分隔标记符字符串</param>
public static string[] SplitPage(string source,string split)
{
int len = split.Length;
ArrayList al = new ArrayList();
int start = 0; //开始位置
int j = -1; //匹配索引位置
while(true)
{
j = source.IndexOf(split,start);
if(j > -1)
{
al.Add(source.Substring(start,j-start));
int s = j-start;
start = j+len;
}
else
{
al.Add(source.Substring(start));
break;
}
}
string[] result;
if(al.Count == 0)
{
string[] r = new string[1];
r[0] = source;
result = r;
}
else
{
string[] r = new string[al.Count];
for(int i = 0; i < al.Count; i++)
{
r[i] = al[i].ToString();
}
result = r;
}
return result;
}
#endregion
}
}