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#用反射原理递归遍历复杂实体对象的更多相关文章
- 21_java之File对象和递归遍历
01IO技术概述 * A:IO技术概述 * a: Output * 把内存中的数据存储到持久化设备上这个动作称为输出(写)Output操作 * b: Input * 把持久设备上的数据读取到内存中的这 ...
- javascript JS递归遍历对象 使用for(variable in object)或者叫for/in和forEach方式
1.递归遍历查找特定key值(ie9以下不支持forEach) 原文http://www.cnblogs.com/ae6623/p/5938560.html var obj = { first: &q ...
- JavaScript对象---递归遍历对象
JavaScript 中的所有事物都是对象:字符串.数值.数组.函数... 此外,JavaScript 允许自定义对象. JavaScript 对象 JavaScript 提供多个内建对象,比如 St ...
- 如何使用递归遍历对象获得value值
一般要用到递归,就要判断对象是否和父类型是否一样 这里演示简单的对象递归,还有数组递归类似. var obj = { a:{w:1,y:2,x:3}, b:{s:4,j:5,x:6}, c:{car: ...
- DataTable转换为Model实体对象
记得在学校的时候,接触得最多的就是SqlHelper,每次在读取的时候不管是DataTable还是DataReader转换为实体对象的时候是最恼火的,因为要写很多代码,而且没有什么意义.后面接触到了反 ...
- 数据结构二叉树的递归与非递归遍历之java,javascript,php实现可编译(1)java
前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序 ...
- 【Away3D代码解读】(二):渲染核心流程(简介、实体对象收集)
我之前解析过Starling的核心渲染流程,相比Away3D而言Starling真的是足够简单,不过幸运的是两者的渲染流程是大体上相似的:Starling的渲染是每帧调用Starling类中的rend ...
- IO-File 文件 目录 基本操作 递归 遍历
创建和删除 //创建文件 File file1 = new File("不存在的文件.txt");//注意,这一步并没有创建文件,只是把磁盘中的文件封装成了一个对象 System. ...
- 项目中常用方法总结(将将DataTable数据集映射到实体对象)【转】
本篇把项目中用到的一些通用方法总结出来, 这些方法因为经常需要在项目中用到,所以把它们归纳在一起, 形成一个.dll 文件是一个理想的选择. 这样也便于日后缩短开发周期. 一. 把一个DataGrid ...
随机推荐
- VSX规划Package文件
VSX是VS扩展,可以针对不同项目编写插件,虽然接触VSX的时间并不多,但是当了解VSX后深刻感受到VSX的魅力. VSX的材料比较少,配置文件也很繁琐,当初我也走了不少弯路. 这篇文章将帮助您更好的 ...
- 开始迈入Csharp的世界了
以前没有学过, 有点兴奋,完全是新手啊. 今天是元宵情人节, 加油↖(^ω^)↗ 分享一些话: 一则拉封丹寓言名字叫寓言<两个朋友>: 一天夜里,一个朋友突然去找另一个朋友.被吵 ...
- Java Concurrency - Concurrent Collections
Data structures are a basic element in programming. Almost every program uses one or more types of d ...
- 【转】Android开发中Handler的使用
在Android开发中,我们经常会遇到这样一种情况:在UI界面上进行某项操作后要执行一段很耗时的代码,比如我们在界面上点击了一个”下载“按钮,那么我们需要执行网络请求,这是一个耗时操作,因为不知道什么 ...
- 在Ubuntu中USB连接手机调试
1.打开手机USB调试功能 显示“开发者选项”(开发者选项默认隐藏,一般需要进入到“设置”-->“关于手机”连续点击七次,可将“开发者选项显示出来”) 将“开发者选项”设置为“开启”状态 打开U ...
- Android之触屏事件
方法一: 新建"MyView"类 package onTouchEvent; import android.content.Context; import android.grap ...
- Ibatis.net防Sql注入
sql注入是一个古老的话题了,但经常会被我们忽略.尤其是使用了ibatis.net之后. Ibatis.net框架对sql注入问题已经做了很好的防护,但经常由于开发人员使用不当,会造成sql的注入隐患 ...
- C/C++笔试题目
1. C语言中无符号数与有符号数 unsigned ; ; printf( printf( ? 有符号数和无符号数在进行比较运算时(==,>=,<=,>,<),有符号数隐式的转 ...
- makefile missing separator. Stop
ifneq ($(KERNELRELEASE),) obj-m := hello.o else PWD := $(shell pwd) KVER := $(shell uname -r) KDIR : ...
- web项目嵌入Jetty运行的两种方式(Jetty插件和自制Jetty服务器)
在开发Java web项目时候,可以在项目中嵌入Jetty服务的方式来运行web程序. 由于最近开发web项目,自己使用的是比较旧的eclipse不支持导入tomcat来运行项目,于是就学习了下使用项 ...