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的所有属性方式来查找和 ...
随机推荐
- lower_bound下确界
//lower_bound用于找到首个大于等于某个值的元素 #include<algorithm> #include<iostream> using namespace std ...
- [Swift实际操作]九、完整实例-(5)创建BaseViewController作为控制器的基类
本文将给项目中的所有视图控制器,创建一份基类.该基类用来定义一些共用的属性和方法. 首先在用来放置视图控制器类的文件夹上点击鼠标右键,打开右键 菜单. 选择[New File]创建文件选项. 在弹出的 ...
- window.open()弹出窗口被拦截
之前有个需求是输入一些配置,然后点击预览,通过接口保存配置并返回预览页面链接,在新页面中打开链接.后来测试一直说没有新页面打开,我一看,原来是被浏览器拦截了. 原因如下: 浏览器只有在认为click和 ...
- 从pg_hba.conf文件谈谈postgresql的连接认证
最近一直在弄postgresql的东西,搭建postgresql数据库集群环境什么的.操作数据库少不得要从远程主机访问数据库环境,例如数据库管理员的远程管理数据库,远程的客户存取数据库文件. 而在po ...
- Python数组(二)
一.函数list 可将任何序列(如字符串)作为list的参数.list实际上是一个类,而不是函数. test=['java','C#','C','C++'] print(list(test)) ——& ...
- SDUT OJ 数据结构实验之链表二:逆序建立链表
数据结构实验之链表二:逆序建立链表 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...
- mysql自动备份并上传至git仓库
自动备份 备份需求 数据库备份的重要性再怎么强调也不为过.当你的操作出现差错,但又因为没有作备份导致数据无法还原时,你就能体会到“万念俱灰”的心情了. 数据库备份有多种形式,本文以我的个人网站数据 ...
- ios网络 -- HTTP请求 and 文件下载/断点下载
一:请求 http://www.jianshu.com/p/8a90aa6bad6b 二:下载 iOS网络--『文件下载.断点下载』的实现(一):NSURLConnection http://www. ...
- 20多个常用的免费WebService接口
20多个常用的免费WebService接口 天气预报Web服务,数据来源于中国气象局 Endpoint Disco WSDL IP地址来源搜索 WEB 服务(是目前最完整的IP地址数据) Endp ...
- Nginx负载均衡详解
upstream mysvr { server 192.168.10.121:3333; server 192.168.10.122:3333; } server { .... location ...