• C#中DataTable与泛型集合互转(支持泛型集合中对象包含枚举)


    最近在做WCF,因为是内部接口,很多地方直接用的弱类型返回(DataSet),这其实是一种非常不好的方式,最近将项目做了修改,将所有接口返回值都修改成强类型,这样可以减少很多与客户端开发人员的沟通,结构内容一目了然

    很多时候,后台我们通过ADO.NET使用SQL语句查询出了想要的数据,这时如果直接把这个DataSet丢给客户端开发人员,会让他们一头雾水,并且维护扩展起来都很麻烦,所以想了一个办法,在服务端,首先我们把查询到的数据集转换成泛型集合,再返回给客户端,客户端可以直接使用,也可以再自行转换成自己需要的数据格式,这样做还有一点是因为,DataTable在进行序列化与反序列化时并不那么可靠,记得在多线程同时序列化一个DataTable时会有异常,另外也隐藏了很多小问题,例如需要序列化DataTable的话必须设置TableName等等

    首先是封装的辅助类,这个辅助类还可以完善,因为我这里数据库数据类型与实体对象的类型可以直接转换,如果实体类类型与数据库内类型不同,则需要做相应的转换

      1 static class Helper
      2     {
      3         /// <summary> 
      4         ///  DataTable转换成泛型集合
      5         /// </summary> 
      6         /// <typeparam name="T">泛型集合类型</typeparam> 
      7         /// <param name="dt">DataTable</param> 
      8         /// <param name="dEnum">字典集合,Key为需要从转换为enum项的DataColumnName,Value为需要转换的枚举的类型</param> 
      9         /// <returns>以实体类为元素的泛型集合</returns> 
     10         public static IList<T> DataTableConvertToListGenuric<T>(DataTable dt, Dictionary<string, Type> dEnum) where T : new()
     11         {
     12             if (dt?.Rows.Count > 0)
     13             {
     14                 // 定义集合 
     15                 List<T> ts = new List<T>();
     16                 // 获得此模型的类型 
     17                 Type type = typeof(T);
     18                 //定义一个临时变量 
     19                 string tempName = string.Empty;
     20                 //遍历DataTable中所有的数据行  
     21                 foreach (DataRow dr in dt.Rows)
     22                 {
     23                     T t = new T();
     24                     //如果T是值类型,则先进行装箱
     25                     object obj = null;
     26                     if (!t.GetType().IsClass)
     27                     {
     28                         obj = t;
     29                     }
     30                     //获得此模型的公共属性 
     31                     PropertyInfo[] propertys = t.GetType().GetProperties();
     32                     //遍历该对象的所有属性 
     33                     foreach (PropertyInfo pi in propertys)
     34                     {
     35                         //将属性名称赋值给临时变量   
     36                         tempName = pi.Name;
     37                         //检查DataTable是否包含此列(列名==对象的属性名)     
     38                         if (dt.Columns.Contains(tempName))
     39                         {
     40                             // 判断此属性是否有Setter   
     41                             if (!pi.CanWrite) continue;//该属性不可写,直接跳出   
     42                             //取值   
     43                             object value = dr[tempName];
     44                             //如果非空,则赋给对象的属性   
     45                             if (value != DBNull.Value)
     46                             {
     47                                 //如果有枚举项
     48                                 if (dEnum != null)
     49                                 {
     50                                     var queryResult = from n in dEnum
     51                                                       where n.Key == tempName
     52                                                       select n;
     53                                     //枚举集合中包含与当前属性名相同的项
     54                                     if (queryResult.Count() > 0)
     55                                     {
     56                                         if (obj != null)
     57                                         {
     58                                             //将字符串转换为枚举对象
     59                                             pi.SetValue(obj, Enum.Parse(queryResult.FirstOrDefault().Value, value.ToString()), null);
     60                                         }
     61                                         else
     62                                         {
     63                                             //将字符串转换为枚举对象
     64                                             pi.SetValue(t, Enum.Parse(queryResult.FirstOrDefault().Value, value.ToString()), null);
     65                                         }
     66                                     }
     67                                     else
     68                                     {
     69                                         if (obj != null)
     70                                         {
     71                                             pi.SetValue(obj, value, null);
     72                                         }
     73                                         else
     74                                         {
     75                                             pi.SetValue(t, value, null);
     76                                         }
     77                                     }
     78                                 }
     79                                 else {
     80                                     if (obj != null)
     81                                     {
     82                                         pi.SetValue(obj, value, null);
     83                                     }
     84                                     else
     85                                     {
     86                                         pi.SetValue(t, value, null);
     87                                     }
     88                                 }
     89                             }
     90                         }
     91                     }
     92                     T ta = default(T);
     93                     //拆箱
     94                     if (obj != null)
     95                     {
     96                         ta = (T)obj;
     97                     }
     98                     else
     99                     {
    100                         ta = t;
    101                     }
    102                     //对象添加到泛型集合中 
    103                     ts.Add(ta);
    104                 }
    105                 return ts;
    106             }
    107             else
    108             {
    109                 throw new ArgumentNullException("转换的集合为空.");
    110             }
    111         }
    112 
    113         /// <summary>
    114         /// 泛型集合转换成DataTable
    115         /// </summary>
    116         /// <typeparam name="T">泛型集合类型</typeparam>
    117         /// <param name="list">泛型集合对象</param>
    118         /// <returns></returns>
    119         public static DataTable ListGenuricConvertToDataTable<T>(List<T> list)
    120         {
    121             if (list?.Count > 0)
    122             {
    123                 Type type = typeof(T);
    124                 PropertyInfo[] properties = type.GetProperties();
    125                 DataTable dt = new DataTable(type.Name);
    126                 foreach (var item in properties)
    127                 {
    128                     dt.Columns.Add(new DataColumn(item.Name) { DataType = item.PropertyType });
    129                 }
    130                 foreach (var item in list)
    131                 {
    132                     DataRow row = dt.NewRow();
    133                     foreach (var property in properties)
    134                     {
    135                         row[property.Name] = property.GetValue(item, null);
    136                     }
    137                     dt.Rows.Add(row);
    138                 }
    139                 return dt;
    140             }
    141             else
    142             {
    143                 throw new ArgumentNullException("转换的集合为空.");
    144             }
    145         }
    146     }

    下面是测试代码

     1     class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             DataTable dt = new DataTable();
     6             dt.Columns.Add("ID", typeof(int));
     7             dt.Columns.Add("Name", typeof(string));
     8             dt.Columns.Add("USex", typeof(string));
     9             dt.Rows.Add(1, "肖潇",Sex.woman);
    10             dt.Rows.Add(2, "何峰涛", Sex.man);
    11             dt.Rows.Add(3, "王萌", Sex.woman);
    12             dt.Rows.Add(4, "汤晓乐", Sex.man);
    13             Dictionary<string, Type> dEnum = new Dictionary<string, Type>();
    14             dEnum.Add("USex", typeof(Sex));
    15             List<User> liUser = (List<User>)Helper.DataTableConvertToListGenuric<User>(dt, dEnum);
    16             Console.WriteLine("DataTable To List<T>");
    17             foreach (var item in liUser)
    18             {
    19                 Console.WriteLine(item.ID + ":" + item.Name+":"+item.USex);
    20             }
    21             Console.WriteLine("================");
    22             DataTable dtConvert = Helper.ListGenuricConvertToDataTable(liUser);
    23             Console.WriteLine("List<T> To DataTable");
    24             foreach (DataRow item in dtConvert.Rows)
    25             {
    26                 Console.WriteLine(item["ID"] + ":" + item["Name"]+":"+(Sex)item["USex"]);
    27             }
    28             Console.ReadKey();
    29         }
    30     }
    31 
    32     struct User
    33     {
    34         public int ID { get; set; }
    35         public string Name { get; set; }
    36         public Sex USex { get; set; }
    37     }
    38 
    39     enum Sex {
    40         man = 0,
    41         woman = 1
    42     }

  • 相关阅读:
    类模型NLP 学习笔记 05 (Brown Clustering && Global Linear Models)
    nullnull精美的文言文表白,一起体会吧!
    [转载]ESFramework介绍之(31)―― 消息分类及对应的处理器
    【转载】ESFramework介绍之(23)―― AgileTcp
    [转载]ESFramework 4.0 快速上手(15) -- 客户端登录验证
    【转载】ESFramework介绍之(31)―― 消息分类及对应的处理器
    【转载】ESFramework 平台下可复用的Tcp通信层实现
    【转载】ESFramework介绍之(27)-- 支持OverdueMessage (离线消息)
    高性能的大型系统经验 -- 将数据分类、并缓存
    【转载】可复用的FS
  • 原文地址:https://www.cnblogs.com/MadisonSky/p/6837313.html
Copyright © 2020-2023  润新知