最近在做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与泛型集合互转(支持泛型集合中对象包含枚举)的更多相关文章

  1. JAVA泛型中的类型擦除及为什么不支持泛型数组

    一,数组的协变性(covariant array type)及集合的非协变性 设有Circle类和Square类继承自Shape类. 关于数组的协变性,看代码: public static doubl ...

  2. C#中DataTable与实体集合通用转换(使用扩展方法)

    本案例提供了:把DataRow转换为单个实体.dataTable转换为List泛型支持时间格式转换. 下文的方法都是扩展方法.扩展方法要求写在静态类中,方法也要静态. 它必须在一个非嵌套.非泛型的静态 ...

  3. 二:C#对象、集合、DataTable与Json内容互转示例;

    导航目录: Newtonsoft.Json 概述 一:Newtonsoft.Json 支持序列化与反序列化的.net 对象类型:    二:C#对象.集合.DataTable与Json内容互转示例: ...

  4. DataTable 和Json 字符串互转

    #region DataTable 转换为Json字符串实例方法 /// <summary> /// GetClassTypeJosn 的摘要说明 /// </summary> ...

  5. java-API中的常用类,新特性之-泛型,高级For循环,可变参数

    API中的常用类 System类System类包含一些有用的类字段和方法.它不能被实例化.属性和方法都是静态的. out,标准输出,默认打印在控制台上.通过和PrintStream打印流中的方法组合构 ...

  6. 对比两个同类型的泛型集合并返回差异泛型集合 ——两个List<类名>的比较

    1: /// <summary> 2: /// 对比两个同类型的泛型集合并返回差异泛型集合 3: /// </summary> 4: /// <typeparam nam ...

  7. Java基础之集合框架类及泛型简介

    Collection接口 Collection 通用的常见方法 add()添加一个元素,可以指定脚标 addAll()将一个collection放入 clear()清除 remove()删除元素,返回 ...

  8. Java基础学习笔记十五 集合、迭代器、泛型

    Collection 集合,集合是java中提供的一种容器,可以用来存储多个数据. 在前面的学习中,我们知道数据多了,可以使用数组存放或者使用ArrayList集合进行存放数据.那么,集合和数组既然都 ...

  9. Java基础---Java---基础加强---内省的简单运用、注解的定义与反射调用、 自定义注解及其应用、泛型及泛型的高级应用、泛型集合的综合

    内省的简单运用: JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则. 采用遍历BeanInfo的所有属性方式来查找和 ...

随机推荐

  1. ubuntu 安装 删除 卸载 Deb 包文件

    图形界面: 安装deb 直接双击图标,输入密码后就可自动安装. 卸载deb 1. 菜单-系统->系统管理->新立得软件包管理器 或 Alt+F2(运行窗口)输入 sudo synaptic ...

  2. 快速搭建hadoop,学习使用

    1.准备Linux环境 1.0先将虚拟机的网络模式选为NAT 1.1修改主机名 vi /etc/sysconfig/network NETWORKING=yes HOSTNAME=myvm ### 1 ...

  3. java 图书馆系统 练习

    话不多说 娱乐 ================================================== book 类(书本的基础属性) package 图书管理系统01; /** * @ ...

  4. webservice怎么给对方提供报文,即wsdl文件

    1.webservice发布后在网页打开服务,点击服务说明 2.打开这样一个页面,ctrl+s保存网页,后缀改为wsdl,搞定

  5. C# 在Winform设计一个耗时较久的任务在后台执行时的状态提示窗口

    很多时候,我们需要在窗体中执行一些耗时比较久的任务.比如:循环处理某些文件,发送某些消息等... 单纯的依靠状态栏,用户体验不佳,按下功能按钮后得不到有效的提醒,小白用户绝对会电话给你说“我点了以后就 ...

  6. luoguP3690 列队

    https://www.luogu.org/problemnew/show/P3960 作为一个初二蒟蒻要考提高组,先做一下17年的题目 我们发现进行一次操作相当于 把第 x 行的第 y 个弹出记为 ...

  7. loj #6013. 「网络流 24 题」负载平衡

    #6013. 「网络流 24 题」负载平衡 题目描述 G 公司有 n nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n nn 个仓库的库存数量相同.搬运货物时 ...

  8. 【算法】关于图论中的最小生成树(Minimum Spanning Tree)详解

    本节纲要 什么是图(network) 什么是最小生成树 (minimum spanning tree) 最小生成树的算法 什么是图(network)? 这里的图当然不是我们日常说的图片或者地图.通常情 ...

  9. 本地localhost:端口号(自己设置的Apache的端口号)打不开问题解决了!开心、哭泣

    想不来自己有多蠢!历经4个月再没学,刚开始xampp的端口问题解决不了,系统竟然会自动改回去端口数据(哭晕) 后来一直显示Apache端口80占用,各种百度之后发现单纯浏览器都访问不了localhos ...

  10. vue框架组件之父子组件之间的通信

    1.如图看解说: 你子标签要给我父标签传递信息,你总得有个触发机制告诉我这是怎么回事对吧  要不我怎么知道你要传数据给我呢!