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的所有属性方式来查找和 ...
随机推荐
- Codeforces Round #551 (Div. 2)A. Serval and Bus
A. Serval and Bus time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- WPF强制设置TextBox文本框的焦点
在需求中遇到这样一种场景:就是在无论何时都要把焦点设置在一个TextBox中. 引用空间:System.Windows.Input 方式1:在窗体的Load事件中去设置焦点,(注意:不能在窗体的构造函 ...
- 谈谈php中抽象类和接口的区别
php中抽象类和接口的区别 1) 概念 面向对象的三大概念:封装,继承,多态 把属性和方法封装起来就是类. 一个类的属性和方法被另外的类复制就是继承,PHP里面的任何类都可以被继承,被继 ...
- LINUX下PHP安装VLD扩展并测试OK
首先下载安装vld压缩包,下载前一定注意区分压缩包版本和php版本是否匹配,否则很可能后面make install 失败. //下载安装包—暂时以14版本为例 wget http://pecl.php ...
- Vue 环境配置
最开始摸element的时候,像盲人摸象,完全没有头绪. https://panjiachen.github.io/vue-element-admin-site/zh/guide/essentials ...
- [USACO06DEC]牛的野餐Cow Picnic DFS
题目描述 The cows are having a picnic! Each of Farmer John's K (1 ≤ K ≤ 100) cows is grazing in one of N ...
- mysql 创建表时注意事项
mysql 创建表时注意事项 mysql 想必大家都不会陌生吧 是我学习中第一个接触的的数据库 已学习就很快上手的 这是一个关系型数据库 不懂什么是关系型数据库 啊哈哈哈 现在知道啦 因 ...
- EA添加时序图
在项目浏览器的空白处右击 http://blog.csdn.net/craftsman1970/article/details/70877530 不同于大部分面向对象或者UML的书籍,在讨论完类图/对 ...
- JavaWeb学习笔记(九)—— JSTL标签库
一.JSTL概述 1.1 什么是JSTL JSTL是apache对EL表达式的扩展(也就是说JSTL依赖EL),JSTL是标签语言!JSTL标签使用以来非常方便,它与JSP动作标签一样,只不过它不是 ...
- Android GPS应用(获取定位信息)
1.介绍 2.使用方法 3.在AndroidManifest.xml文件中添加 <uses-permission android:name="android.permission.AC ...