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# LINQ(3)
我们还是接着讨论一下group by 这一章节讨论group的本质:分组. 分组之后进行存储或者查询. 这个时候就要用一个新的关键字:into 这个之后就group就不作为结尾了. 必须重写另起sel ...
- NSKeyedArchiver数据归档
前言 在 OC 语言中,归档是一个过程,即用某种格式来保存一个或多个对象,以便以后还原这些对象. 通常,这个过程包括将(多个)对象写入文件中,以便以后读取该对象.可以使用归档的方法进行对象的深复制. ...
- django中ModelForm解决多表单组合显示问题
一.多表单组合显示问题 在项目中用ModelForm生成页面时 当有多表单组合显示时,会显示全部的关联表单数据. 而在实际项目中可能会出现只想让用户选择部分数据,这时候这样的显示就有问题. 二.问题解 ...
- 详细解读Python中的__init__()方法
init()方法意义重大的原因有两个.第一个原因是在对象生命周期中初始化是最重要的一步:每个对象必须正确初始化后才能正常工作.第二个原因是init()参数值可以有多种形式. 因为有很多种方式为init ...
- 用 GitLab CI 进行持续集成
简介 从 GitLab 8.0 开始,GitLab CI 就已经集成在 GitLab 中,我们只要在项目中添加一个 .gitlab-ci.yml 文件,然后添加一个 Runner,即可进行持续集成. ...
- struts2学习笔记(六)—— 拦截器
一.拦截器概述 拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前进行拦截,然后在之前或之后加入某些操作.拦截器是AOP的一种实现策略. 在We ...
- Miller_Rabin素数测试【学习笔记】
引语:在数论中,对于素数的研究一直就很多,素数测试的方法也是非常多,如埃式筛法,6N±1法,或者直接暴力判(试除法).但是如果要判断比较大的数是否为素数,那么传统的试除法和筛法都不再适用.所以我们需要 ...
- dataTable 加了竖向滚动条导致列头样式错位的问题 / 亲测可用,不好用你打我,用好了记得点推荐
tab在没有显示之前,容器是没有高度宽度的,而dt在自动计算高度和宽度时是获取的外部容器的高度和宽度,当切换tab时,dt获取不到这个高度宽度,导致列头都挤在一起,是用下面代码解决此问题 $('a[d ...
- HDU - 2203 KMP水题
循环移位的套路操作就是一份折开变两份 /*H E A D*/ void match(){ int n=strlen(T+1); int m=strlen(P+1); int j=0; rep(i,1, ...
- 日志统计--蓝桥杯--vector
/* 标题:日志统计 小明维护着一个程序员论坛.现在他收集了一份"点赞"日志,日志共有N行.其中每一行的格式是: ts id 表示在ts时刻编号id的帖子收到一个"赞&q ...