c#用反射原理递归遍历复杂实体对象

之前在网上看到的都是遍历那种比较简单的实体对象,但是如果有实体嵌套,甚至是包含有List<XXInfo>这种属性的时候就没有办法处理了。通过递归遍历的方式可以完成对复杂实体对象的所有属性的遍历,可以取值和赋值。

下面是关键部分的代码,有什么不对的地方路过的大大一定要指点哈。

using System.Reflection;

public System.Text.StringBuilder strB = new System.Text.StringBuilder();
    public void GetInfoPropertys(object objInfo)
    {         if (objInfo ==
null) return;         Type tInfo =
objInfo.GetType();         PropertyInfo[]
pInfos = tInfo.GetProperties();         if
(tInfo.IsGenericType)         {
           
System.Collections.ICollection Ilist = objInfo as
System.Collections.ICollection;
            if (Ilist !=
null)             {
               
strB.AppendFormat("集合子属性{0}<br/>", Ilist.Count);
               
foreach (object obj in Ilist)
               
{
                   
GetInfoPropertys(obj);
               
}             }
            else
            {
               
strB.Append("泛型集合为空<br/>");
            }
            return;
        }
        foreach (PropertyInfo pTemp in
pInfos)         {
            string Pname
= pTemp.Name;            
string pTypeName = pTemp.PropertyType.Name;
            object Pvalue
= pTemp.GetValue(objInfo, null);
            if
(pTemp.PropertyType.IsValueType || pTemp.PropertyType.Name.StartsWith("String"))
            {
               
string value = (Pvalue == null ? "为空" : Pvalue.ToString());
               
strB.AppendFormat("属性名:{0},属性类型:{1},属性值:{2}<br/>", Pname, pTypeName,
value);             }
            else
            {
               
string value = Pvalue == null ? "为空" : Pvalue.ToString();
               
strB.AppendFormat("<br/><b>子类</b>,属性名:{0},属性类型:{1},属性值:{2}<br/>",
Pname, pTypeName, value);
               
strB.Append("----------------------------------------------<br/>");
               
GetInfoPropertys(Pvalue);

}

}     }

利用反射实现表格式Excel文档的导出:

上次客户提出了要将数据导出到类似上图的固定格式的Excel文档中,当然真实的表格不是上面那样的,而且表格的格式有十多种,最后采用的解决办法就是利用C#的反射。大概的思路是这样的,为每种导出的表格样式都做一个xml的配置文件,然后记录每个需要复制的文本框的坐标,以及这个值在实体类中的名称,针对上面的那种表格格式,xml配置文件是这样的:

<?xml version="1.0" encoding="utf-8"?> <XML
TableName="table1.xml" OtherInfo="">

  <Field Fname="NAME" PropertyName="NAME" Desc="姓名">
    <x>4</x>     <y>3</y>
  </Field>   <Field Fname="SEX" PropertyName="SEX"
Desc="性别">     <x>10</x>    
<y>3</y>   </Field>   <Field Fname="BIRTHDAY"
PropertyName="BIRTHDAY" Desc="出生年月">     <x>4</x>
    <y>4</y>   </Field>   <Field
Fname="Zz" PropertyName="Zz" Desc="政治面貌">    
<x>10</x>     <y>4</y>  
</Field>   <Field Fname="HunYin" PropertyName="HunYin"
Desc="婚姻状况">     <x>4</x>    
<y>5</y>   </Field>   <Field Fname="Tel"
PropertyName="Tel" Desc="联系电话">     <x>10</x>
    <y>5</y>   </Field>   <Field
Fname="WorkHistory" PropertyName="WorkHistory" Desc="工作经历">
    <x>13</x>     <y>1</y>
  </Field>

  <!--Field Fname="SaleGuid" 
PropertyName="SaleList.SaleGuid" Desc="销售记录编号">    
<x></x>     <y></y>  
</Field-->   <Field Fname="ProductGuid" 
PropertyName="SaleList.ProductGuid" Desc="货物编号">    
<x>1</x>     <y>8</y>  
</Field>   <Field Fname="ProductName" 
PropertyName="SaleList.ProductName" Desc="产品编号">    
<x>3</x>     <y>8</y>  
</Field>   <Field Fname="ProductJiage" 
PropertyName="SaleList.ProductJiage" Desc="售价">    
<x>5</x>     <y>8</y>  
</Field>   <Field Fname="SaleDate" 
PropertyName="SaleList.SaleDate" Desc="出售日期">    
<x>7</x>     <y>8</y>  
</Field> </XML>

然后从数据库中获取数据存入到实体类中,用反射遍历实体类的所有属性,如果xml中得PropertyName节点的值和当前属性的属性名相等,那么就可以通过xml提供的坐标给Excel表格赋值了。这样做的一个好处是,可以实现不同表格的通用赋值,即使翻页显示也能应对(比如上面的销售记录每页只能显示4条,而程序中是构造的10条销售记录,只能通过分页显示完),不用为每种格式都去写一种实现,即使表格的样式有所变动也不用改程序,只需更改一下xml就好了。

语言组织和表达的能力不行,还是直接上码:

using System; using System.Collections.Generic; using System.Web; using
System.Reflection; using System.Xml; /// <summary> ///Excel导出 ///
</summary> public class ExcelExport {

#region 变量     public List<FiledInfo>
FInfoList = new List<FiledInfo>();//xml属性、坐标列表     //public
System.Text.StringBuilder strB = new System.Text.StringBuilder();
    ExcelOperator excel = null;//Excel操作     int
sheetIndex = 0;//excel工作薄索引     #endregion    
public ExcelExport()     {
        getNodeFromXml();    
}     /// <summary>     /// 模拟从数据库获取数据
    /// </summary>     ///
<returns></returns>     public employee GetInfo()
    {         employee e = new
employee();         e.NAME = "路人甲";
        e.SEX = true;
        e.HunYin = false;
        e.Tel = "15986752131";
        e.Zz = "团员";
        e.WorkHistory = "暂无";
        for (int i = 0; i < 10; i++)
        {
            SaleInfo s =
new SaleInfo();
            s.ProductGuid
= "产品编号" + i;            
s.ProductName = "产品名称" + i;
           
s.ProductJiage = 10.23M * i;
            s.SaleDate =
DateTime.Now.AddDays(i);
           
e.SaleList.Add(s);         }
        return e;     }

//public string GetProperties()     //{
    //    employee emp = GetInfo();
    //    GetProperty(emp, "");    
//    return strB.ToString();     //}
    //private void GetProperty(object obj, string parentProName)
    //{     //    if (obj == null)
return;     //    Type t = obj.GetType();
    //    string strParentProName =
(string.IsNullOrEmpty(parentProName) ? "" : parentProName.TrimEnd(‘.‘) + ".");
    //    if (t.IsGenericType)    
//    {    
//        System.Collections.ICollection ic =
obj as System.Collections.ICollection;    
//        foreach (object objTemp in ic)
    //        {
   
//           
strB.Append("---------------------<br/>");    
//           
GetProperty(objTemp, strParentProName);    
//        }    
//    }     //    else
    //    {    
//        foreach (PropertyInfo pTemp in
t.GetProperties())    
//        {    
//            string name
= pTemp.Name;    
//            string
typeName = pTemp.PropertyType.FullName;    
//            object
value = pTemp.GetValue(obj, null);    
//            if
(pTemp.PropertyType.IsValueType || pTemp.PropertyType.Name.StartsWith("String"))
   
//            {
   
//               
strB.AppendFormat("属性名:{0},类型名称:{1},属性值:{2}<br/>", strParentProName +
name, typeName, value);    
//            }
   
//            else
   
//            {
   
//               
GetProperty(value, name);    
//               
strB.AppendFormat("属性名:{0},类型名称:{1},属性值:{2}<br/>", name, typeName,
value);

//            }
    //        }
    //    }     //}
    /// <summary>     /// 属性赋值
    /// </summary>     private void
SetPropertyValues(object obj, string parentProName, int index)
    {         if (obj == null)
return;         Type t = obj.GetType();
        string strParentProName =
(string.IsNullOrEmpty(parentProName) ? "" : parentProName.TrimEnd(‘.‘) + ".");
        if (t.IsGenericType)
        {
           
System.Collections.IList ic = obj as System.Collections.IList;
            int ICIndex =
0;             foreach
(object objTemp in ic)
            {
               
//strB.Append("---------------------<br/>");
               
SetPropertyValues(objTemp, strParentProName, ICIndex);
               
ICIndex++;             }
        }
        else
        {
            foreach
(PropertyInfo pTemp in t.GetProperties())
            {
               
string name = pTemp.Name;
               
string typeName = pTemp.PropertyType.FullName;
               
object value = pTemp.GetValue(obj, null);
               
if (pTemp.PropertyType.IsValueType ||
pTemp.PropertyType.Name.StartsWith("String"))
               
{
                   
FiledInfo finfoResult = FInfoList.Find(delegate(FiledInfo finfo) { return
finfo.PropertyName == strParentProName + name; });
                   
if (finfoResult != null)
                   
{
                       
//strB.AppendFormat("属性名:{0},属性值:{1},坐标:x={2},y={3}<br/>",
strParentProName + name, value,finfoResult.X,finfoResult.Y);
                       
int x = Convert.ToInt32(finfoResult.X) + index;
                       
int y = Convert.ToInt32(finfoResult.Y);
                       
excel.SetCellValue(sheetIndex, x, y, value.ToString());
                   
}
               
}
               
else
               
{
                   
SetPropertyValues(value, name, 0);
               
}             }
        }     }
    /// <summary>     ///    
/// </summary>     public employee SetPropertyValue()
    {         if (excel ==
null)         {
            excel = new
ExcelOperator(@"D:\程序开发\我写的东东\webLX\Excel\model\yuangong.xls");
        }
        employee emp = GetInfo();
        List<employee> list =
FormatEmplyeeObj(emp);         for (int i =
0; i < list.Count;i++ )         {
            if (i != 0)
            {
               
excel.CreateNewSheetByCopy("销售记录" + i.ToString());
            }
        }
        foreach (employee empTemp in list)
        {
            sheetIndex++;
           
SetPropertyValues(empTemp, "", 0);         }
        excel.Close(true);
        return emp;     }
    /// <summary>     /// 设置值
    /// </summary>     private void
SetValue()     {        
employee e = new employee();         Type t =
e.GetType();

}

private void getNodeFromXml()     {
        FInfoList.Clear();
        string strXmlPath =
@"D:\程序开发\我写的东东\webLX\Excel\modelXML\table1.xml";
        XmlDocument xml = new XmlDocument();
        xml.Load(strXmlPath);
        XmlNodeList nodelist =
xml.GetElementsByTagName("Field");        
foreach (XmlNode node in nodelist)         {
            FiledInfo
finfo = new FiledInfo();
           
finfo.PropertyName = node.Attributes["PropertyName"].Value;
            finfo.X =
node.ChildNodes[1].InnerText;
            finfo.Y =
node.ChildNodes[0].InnerText;
           
FInfoList.Add(finfo);         }
    }     /// <summary>    
/// 格式化员工对象,便于翻页显示     /// </summary>    
public List<employee> FormatEmplyeeObj(employee emp)     {
        List<employee> list = new
List<employee>();         if (emp !=
null)         {
            if
(emp.SaleList.Count > 4)//销售记录每页显示4行
            {
               
for (int i = 0; i < Math.Ceiling(Convert.ToDouble(emp.SaleList.Count) / 4);
i++)
               
{
                   
employee infoTemp = new employee();
                   
CloneEntityObject(emp, infoTemp);
                   
if ((i + 1) * 4 > emp.SaleList.Count)
                   
{
                       
infoTemp.SaleList = infoTemp.SaleList.GetRange(i * 4,
emp.SaleList.Count-i*4);//销售记录每页显示四行
                   
}
                   
else
                   
{
                       
infoTemp.SaleList = infoTemp.SaleList.GetRange(i * 4, 4);//销售记录每页显示四行
                   
}
                   
list.Add(infoTemp);
               
}             }
        }
        return list;     }
    /// <summary>     /// 实体对象拷贝
    /// </summary>     /// <param
name="srcObj"></param>     /// <param
name="desObj"></param>     public void
CloneEntityObject(object srcObj, object desObj)     {
        if (srcObj.Equals(desObj))
        {
            return;
        }
        if (srcObj.GetType() !=
desObj.GetType())         {
            return;
        }
        System.Reflection.PropertyInfo[] info
= srcObj.GetType().GetProperties();        
foreach (System.Reflection.PropertyInfo property in info)
        {
           
desObj.GetType().GetProperty(property.Name).SetValue(desObj,
           
srcObj.GetType().GetProperty(property.Name).GetValue(srcObj, null), null);
        }     }

}

另外Excel的操作类在之前的文章中有,这里就不再贴了。

c#用反射原理递归遍历复杂实体对象,码迷,mamicode.com

时间: 2024-10-12 16:56:26

c#用反射原理递归遍历复杂实体对象的相关文章

foreach遍历访问的对象必须实现IEnumerable 或声明GetEnumerator

需要实现一个对象为可遍历的对象,必须实现IEnumerable或声明GetEnumerator 方法,其中,IEnumerable 不是必须实现,但是GetEnumerator 方法则必须声明: 例如,先声明一个Item类,该类用于遍历的实体 //先声明一个Item的对象,用于遍历的实体对象 public class Item { public int Id; public string Name; public int Price; public Item(int id, string nam

如何使用递归遍历对象获得value值

一般要用到递归,就要判断对象是否和父类型是否一样 这里演示简单的对象递归,还有数组递归类似. var obj = { a:{w:1,y:2,x:3}, b:{s:4,j:5,x:6}, c:{car:7,cat:8,mao:9} } function f(s){ for(var i in s){ if(typeof s[i]=="object"){ f(s[i]) }else{ console.log(s[i]); } } } f(obj); 返回结果:1,2,3,4,5,6,7,8,

二叉树之非递归遍历

1.二叉树的遍历 为什么要有遍历操作:将线性结构-------->非线性结构: 将递归程序-------->非递归程序: 2.二叉树的三种递归遍历: 先序遍历:先访问根(父)结点,在访问左分支,最后访问右分支: 中序遍历:先访问左分支,在根结点,最后右分支: 后序遍历:先访问左分支,在访问右分支,最后访问根节点: 所有程序皆正确测试过,后面将给完整程序和测试程序,测试结果. 以下就是递归遍历,先序,中序,后序: 下面的都是在类外定义的函数,所以为模板函数: //先序遍历 template<

利用反射自动封装成实体对象

利用此方法的时候需要传递的参数的名称,必须以行号结尾,去掉行号就是属性名称,比如页面传递name+rowNo,那么实体对象的属性名应该为name.代码如下 //获取页面数据,自动封装成bean对象 public List getObjectList(Class clazz,String[] rowNos) throws Exception{ List objList = new ArrayList(); for(int i=0;rowNos!=null && i<rowNos.len

【Away3D代码解读】(二):渲染核心流程(简介、实体对象收集)

我之前解析过Starling的核心渲染流程,相比Away3D而言Starling真的是足够简单,不过幸运的是两者的渲染流程是大体上相似的:Starling的渲染是每帧调用Starling类中的render方法,类似的Away3D的渲染是每帧调用View3D类中的render方法,那我们要了解Away3D的渲染就需要从这个方法入手了. View3D的render方法源码: 1 /** 2 * Renders the view. 3 */ 4 public function render():voi

数据结构 树的遍历(递归遍历)

//树的遍历--递归遍历 #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct _TreeNode{ //数据域 char data; //指针域 struct _TreeNode * leftchild;//左孩子指针 struct _TreeNode * rightchild;//右孩子指针 }TreeNode, *TreeNodePointer; //先序遍历 void Pri

数据结构二叉树的递归与非递归遍历之 实现可编译(1)java

前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序遍历为例进行说明,中序遍历和后序遍历,以此类推! 二叉树递归与非递归遍历的区别,虽然递归遍历,跟容易读懂,代码量少,运算快,但是却容易出现溢出的问题,所以所以非递归遍历,在处理千万级的运算量时会先的很有用处. 二叉树的先序遍历:先访问根节点,再访问先后访问左右节点.如图: 二叉树的递归遍历之java

递归与非递归遍历文件目录

递归遍历目录的缺点:遇到多层级目录时,层级越多,堆栈的负荷越大. [java] view plaincopyprint? import java.io.File; import java.util.LinkedList; /* * 采用非递归方式遍历目录及其子目录的文件 */ public class ProcessDirectory { public static int num;//文件总量 public static void main(String[] args) { String pa

递归遍历

递归遍历: 查找指定父节点下所有子代节点 如何: 2步:    1. 先遍历所有直接子节点   2. 在遍历直接子节点时,对每个子节点调用和父节点完全相同的方法. 算法: 深度优先遍历: 每次都优先遍历子节点 所有子节点遍历完,才返回遍历兄弟节点 递归的效率: 极低. 解决: 绝大多数递归都可用循环代替 遍历API: 每次仅遍历下一个节点,可用循环反复执行(了解) 1. 节点迭代器: 如何: 2步: 1. 创建迭代器对象: var iterator=document.createNodeIter