C#中DataTable与泛型集合互转(支持泛型集合中对象包含枚举)
最近在做WCF,因为是内部接口,很多地方直接用的弱类型返回(DataSet),这其实是一种非常不好的方式,最近将项目做了修改,将所有接口返回值都修改成强类型,这样可以减少很多与客户端开发人员的沟通,结构内容一目了然
很多时候,后台我们通过ADO.NET使用SQL语句查询出了想要的数据,这时如果直接把这个DataSet丢给客户端开发人员,会让他们一头雾水,并且维护扩展起来都很麻烦,所以想了一个办法,在服务端,首先我们把查询到的数据集转换成泛型集合,再返回给客户端,客户端可以直接使用,也可以再自行转换成自己需要的数据格式,这样做还有一点是因为,DataTable在进行序列化与反序列化时并不那么可靠,记得在多线程同时序列化一个DataTable时会有异常,另外也隐藏了很多小问题,例如需要序列化DataTable的话必须设置TableName等等
首先是封装的辅助类,这个辅助类还可以完善,因为我这里数据库数据类型与实体对象的类型可以直接转换,如果实体类类型与数据库内类型不同,则需要做相应的转换
static class Helper
{
/// <summary>
/// DataTable转换成泛型集合
/// </summary>
/// <typeparam name="T">泛型集合类型</typeparam>
/// <param name="dt">DataTable</param>
/// <param name="dEnum">字典集合,Key为需要从转换为enum项的DataColumnName,Value为需要转换的枚举的类型</param>
/// <returns>以实体类为元素的泛型集合</returns>
public static IList<T> DataTableConvertToListGenuric<T>(DataTable dt, Dictionary<string, Type> dEnum) where T : new()
{
if (dt?.Rows.Count > )
{
// 定义集合
List<T> ts = new List<T>();
// 获得此模型的类型
Type type = typeof(T);
//定义一个临时变量
string tempName = string.Empty;
//遍历DataTable中所有的数据行
foreach (DataRow dr in dt.Rows)
{
T t = new T();
//如果T是值类型,则先进行装箱
object obj = null;
if (!t.GetType().IsClass)
{
obj = t;
}
//获得此模型的公共属性
PropertyInfo[] propertys = t.GetType().GetProperties();
//遍历该对象的所有属性
foreach (PropertyInfo pi in propertys)
{
//将属性名称赋值给临时变量
tempName = pi.Name;
//检查DataTable是否包含此列(列名==对象的属性名)
if (dt.Columns.Contains(tempName))
{
// 判断此属性是否有Setter
if (!pi.CanWrite) continue;//该属性不可写,直接跳出
//取值
object value = dr[tempName];
//如果非空,则赋给对象的属性
if (value != DBNull.Value)
{
//如果有枚举项
if (dEnum != null)
{
var queryResult = from n in dEnum
where n.Key == tempName
select n;
//枚举集合中包含与当前属性名相同的项
if (queryResult.Count() > )
{
if (obj != null)
{
//将字符串转换为枚举对象
pi.SetValue(obj, Enum.Parse(queryResult.FirstOrDefault().Value, value.ToString()), null);
}
else
{
//将字符串转换为枚举对象
pi.SetValue(t, Enum.Parse(queryResult.FirstOrDefault().Value, value.ToString()), null);
}
}
else
{
if (obj != null)
{
pi.SetValue(obj, value, null);
}
else
{
pi.SetValue(t, value, null);
}
}
}
else {
if (obj != null)
{
pi.SetValue(obj, value, null);
}
else
{
pi.SetValue(t, value, null);
}
}
}
}
}
T ta = default(T);
//拆箱
if (obj != null)
{
ta = (T)obj;
}
else
{
ta = t;
}
//对象添加到泛型集合中
ts.Add(ta);
}
return ts;
}
else
{
throw new ArgumentNullException("转换的集合为空.");
}
} /// <summary>
/// 泛型集合转换成DataTable
/// </summary>
/// <typeparam name="T">泛型集合类型</typeparam>
/// <param name="list">泛型集合对象</param>
/// <returns></returns>
public static DataTable ListGenuricConvertToDataTable<T>(List<T> list)
{
if (list?.Count > )
{
Type type = typeof(T);
PropertyInfo[] properties = type.GetProperties();
DataTable dt = new DataTable(type.Name);
foreach (var item in properties)
{
dt.Columns.Add(new DataColumn(item.Name) { DataType = item.PropertyType });
}
foreach (var item in list)
{
DataRow row = dt.NewRow();
foreach (var property in properties)
{
row[property.Name] = property.GetValue(item, null);
}
dt.Rows.Add(row);
}
return dt;
}
else
{
throw new ArgumentNullException("转换的集合为空.");
}
}
}
下面是测试代码
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("USex", typeof(string));
dt.Rows.Add(, "肖潇",Sex.woman);
dt.Rows.Add(, "何峰涛", Sex.man);
dt.Rows.Add(, "王萌", Sex.woman);
dt.Rows.Add(, "汤晓乐", Sex.man);
Dictionary<string, Type> dEnum = new Dictionary<string, Type>();
dEnum.Add("USex", typeof(Sex));
List<User> liUser = (List<User>)Helper.DataTableConvertToListGenuric<User>(dt, dEnum);
Console.WriteLine("DataTable To List<T>");
foreach (var item in liUser)
{
Console.WriteLine(item.ID + ":" + item.Name+":"+item.USex);
}
Console.WriteLine("================");
DataTable dtConvert = Helper.ListGenuricConvertToDataTable(liUser);
Console.WriteLine("List<T> To DataTable");
foreach (DataRow item in dtConvert.Rows)
{
Console.WriteLine(item["ID"] + ":" + item["Name"]+":"+(Sex)item["USex"]);
}
Console.ReadKey();
}
} struct User
{
public int ID { get; set; }
public string Name { get; set; }
public Sex USex { get; set; }
} enum Sex {
man = ,
woman =
}

C#中DataTable与泛型集合互转(支持泛型集合中对象包含枚举)的更多相关文章
- JAVA泛型中的类型擦除及为什么不支持泛型数组
一,数组的协变性(covariant array type)及集合的非协变性 设有Circle类和Square类继承自Shape类. 关于数组的协变性,看代码: public static doubl ...
- C#中DataTable与实体集合通用转换(使用扩展方法)
本案例提供了:把DataRow转换为单个实体.dataTable转换为List泛型支持时间格式转换. 下文的方法都是扩展方法.扩展方法要求写在静态类中,方法也要静态. 它必须在一个非嵌套.非泛型的静态 ...
- 二:C#对象、集合、DataTable与Json内容互转示例;
导航目录: Newtonsoft.Json 概述 一:Newtonsoft.Json 支持序列化与反序列化的.net 对象类型: 二:C#对象.集合.DataTable与Json内容互转示例: ...
- DataTable 和Json 字符串互转
#region DataTable 转换为Json字符串实例方法 /// <summary> /// GetClassTypeJosn 的摘要说明 /// </summary> ...
- java-API中的常用类,新特性之-泛型,高级For循环,可变参数
API中的常用类 System类System类包含一些有用的类字段和方法.它不能被实例化.属性和方法都是静态的. out,标准输出,默认打印在控制台上.通过和PrintStream打印流中的方法组合构 ...
- 对比两个同类型的泛型集合并返回差异泛型集合 ——两个List<类名>的比较
1: /// <summary> 2: /// 对比两个同类型的泛型集合并返回差异泛型集合 3: /// </summary> 4: /// <typeparam nam ...
- Java基础之集合框架类及泛型简介
Collection接口 Collection 通用的常见方法 add()添加一个元素,可以指定脚标 addAll()将一个collection放入 clear()清除 remove()删除元素,返回 ...
- Java基础学习笔记十五 集合、迭代器、泛型
Collection 集合,集合是java中提供的一种容器,可以用来存储多个数据. 在前面的学习中,我们知道数据多了,可以使用数组存放或者使用ArrayList集合进行存放数据.那么,集合和数组既然都 ...
- Java基础---Java---基础加强---内省的简单运用、注解的定义与反射调用、 自定义注解及其应用、泛型及泛型的高级应用、泛型集合的综合
内省的简单运用: JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则. 采用遍历BeanInfo的所有属性方式来查找和 ...
随机推荐
- 指针和动态分配内存 (不定长度数组)------新标准c++程序设计
背景: 数组的长度是定义好的,在整个程序中固定不变.c++不允许定义元素个数不确定的数组.例如: int n; int a[n]; //这种定义是不允许的 但是在实际编程中,往往会出现要处理的数据数量 ...
- 上课总结-数据库Chapter2: 关系数据库
Chapter2: 关系数据库 一.搞懂主键 外键关系 主键(主码):能唯一标识一个元组的某一属性组. 外键:不是这组数据的主键 但是另一组数据的唯一主键(当这组数据的主键有2个时 可以作为外键) 例 ...
- CLion中出现错误add_dependencies called with incorrect number of arguments解决
出现这个错误以后我以为是IDE出现问题了,可是重新启动,打开其他的工程文件以后发现并没有这个错误,但是新建的文件却报错 然后就打开其他工程的Cmake_list.txt文件,发现最后一行是有工程文件夹 ...
- 【大数据系统架构师】0.1 Java编程基础
1. 初识Java 2. Java语法 快速入门点我 2.1 数据类型和运算符 2.2 流程控制语句 2.3 数组 2.4 类和对象 2.5 OOP三大特性 2.6 集合框架与泛型 2.7 反射机制 ...
- CF1137E. Train Car Selection(可删堆)
题面 三个操作 1.在当前数列最左端加入\(k\)个初始为\(0\)的数 2.在当前数列最右端加入\(k\)个初始为\(0\)的数 3.将当前数列从左到右第\(i\)个数加上\(b+(i-1)k(b& ...
- app.use和app.get的区别及解析
转载至:http://blog.csdn.net/wthfeng/article/details/53366169 写在前面:最近研究nodejs及其web框架express,对app.use和app ...
- html基础知识,整理
# HMTL 基础知识 ###查看网页源代码吗 ``` ctrl + u``` ###dom元素 一个标签即代表一个dom元素 ###dom元素属性 ``` <p id ="first ...
- vue 在路由中复用组件
首先需要在app.vue中引入: <template> <div id="app"> <!--<app-header></app-h ...
- url 路径的拼接
url 路径的拼接 刚开始做项目总是被路径所困扰,不知道何时该拼接,何时不拼接,怎么拼接,如何拼接,有像地址栏拼接一样的,又在跳转页面拼接的,还有在 a 标签中 href 中拼接的 ,当时做的时候一 ...
- Python之freshman02
内置方法:https://docs.python.org/3/library/functions.html?highlight=built#abs 一.数学运算 1.abs()-取绝对值 2.divm ...