zoukankan      html  css  js  c++  java
  • 【原】超简单类型转换(DataTable > List/JSON)的实现

    背景:

    开发工作中经常需要类型的转换,比如DataTable转换为List、或是DataTable转换为JSON等等,

    每次都重复的写相同的代码,比如:把实体类的字段属性一个一个的列出来,从DataTabel中把值取出来赋上,

    真的好麻烦 (*=*)

    思考:

    1)DataTable转换为List,主要是使用反射,遍历实体类的属性,和DataTabel中的列进行对比并赋值

    2)DataTable转换为JSON,主要是拼接JSON串

    实践:

    参考了网上很多前辈的思路和实现,制作了一个ConvertHelper类,感谢各位前辈 ^_^

    转换辅助类ConvertHelper代码如下,覆盖范围包括属性和公共字段:

    ConvertHelper
      1 /// <summary>
      2 /// 转换辅助类
      3 /// </summary>
      4 /// <typeparam name="T"></typeparam>
      5 public class ConvertHelper<T> where T : new()
      6 {
      7     /// <summary>
      8     /// DataTable-->List
      9     /// </summary>
     10     /// <param name="dt">DataTable</param>
     11     /// <returns></returns>
     12     public static IList<T> DataTableConvertToList(DataTable dt)
     13     {
     14         IList<T> ts = new List<T>();
     15 
     16         // 取得泛型的类型
     17         Type type = typeof(T);
     18 
     19         // 创建类型的对象(用于比较用)
     20         //object convertObj = Activator.CreateInstance(type, null);
     21 
     22         // 反射取得类型实例的属性数组
     23         //PropertyInfo[] propertys = convertObj.GetType().GetProperties();
     24         PropertyInfo[] propertys = type.GetProperties();
     25 
     26         // 反射取得类型实例的字段数组
     27         FieldInfo[] fields = type.GetFields();
     28 
     29         foreach (DataRow dr in dt.Rows)
     30         {
     31             // 创建类型的对象(用于赋值用)
     32             //object outputObj = Activator.CreateInstance(type, null);
     33             T outputObj = new T();
     34 
     35             // 遍历字段(公共字段)
     36             foreach (FieldInfo fi in fields)
     37             {
     38                 // 如果DataTable的数据列中包含有对应的字段
     39                 if (dt.Columns.Contains(fi.Name))
     40                 {
     41                     // 取得字段的值
     42                     object value = dr[fi.Name];
     43 
     44                     if (value != DBNull.Value)
     45                     {
     46                         // 将对应字段的值赋给创建的类型实例的对应的字段
     47                         fi.SetValue(outputObj, value);
     48                     }
     49                 }
     50             }
     51 
     52             // 遍历属性
     53             foreach (PropertyInfo pi in propertys)
     54             {
     55                 // 如果DataTable的数据列中包含有对应的属性
     56                 if (dt.Columns.Contains(pi.Name))
     57                 {
     58                     if (!pi.CanWrite)
     59                     {
     60                         continue;
     61                     }
     62 
     63                     // 取得属性的值
     64                     object value = dr[pi.Name];
     65 
     66                     if (value != DBNull.Value)
     67                     {
     68                         // 将对应属性的值赋给创建的类型实例的对应的属性
     69                         pi.SetValue(outputObj, value, null);
     70                     }
     71                 }
     72             }
     73 
     74             // 添加到List中
     75             ts.Add((T)outputObj);
     76         }
     77 
     78         return ts;
     79     }
     80 
     81     /// <summary>
     82     /// DataTable-->Json
     83     /// </summary>
     84     /// <param name="dt">DataTable</param>
     85     /// <returns></returns>
     86     public static string DataTableConvertToJson(DataTable dt)
     87     {
     88         StringBuilder jsonBuilder = new StringBuilder();
     89 
     90         // 拼接JSON串
     91         jsonBuilder.Append("{\"");
     92         jsonBuilder.Append(dt.TableName);
     93         jsonBuilder.Append("\":[");
     94         for (int i = 0; i < dt.Rows.Count; i++)
     95         {
     96             jsonBuilder.Append("{");
     97             for (int j = 0; j < dt.Columns.Count; j++)
     98             {
     99                 jsonBuilder.Append("\"");
    100                 jsonBuilder.Append(dt.Columns[j].ColumnName);
    101                 jsonBuilder.Append("\":\"");
    102                 jsonBuilder.Append(dt.Rows[i][j].ToString());
    103                 jsonBuilder.Append("\",");
    104             }
    105             jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
    106             jsonBuilder.Append("},");
    107         }
    108         jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
    109         jsonBuilder.Append("]");
    110         jsonBuilder.Append("}");
    111 
    112         return jsonBuilder.ToString();
    113     }
    114 
    115     /// <summary>
    116     /// DataSet-->Json
    117     /// </summary>
    118     /// <param name="ds">DataSet</param>
    119     /// <returns></returns>
    120     public static string DataSetConvertToJson(DataSet ds)
    121     {
    122         StringBuilder json = new StringBuilder();
    123 
    124         foreach (DataTable dt in ds.Tables)
    125         {
    126             // 拼接JSON串
    127             json.Append("{\"");
    128             json.Append(dt.TableName);
    129             json.Append("\":");
    130             json.Append(DataTableConvertToJson(dt));
    131             json.Append("}");
    132         }
    133         
    134         return json.ToString();
    135     }
    136 }

    如何使用呢?

    很方便的,先定义一个实体类UserInfo,定义了13个字段

    UserInfo
     1 /// <summary>
     2 /// 用户信息实体
     3 /// </summary>
     4 public class UserInfo
     5 {
     6     /// <summary>
     7     /// 用户编号
     8     /// </summary>
     9     public int UserID { get; set; }
    10 
    11     /// <summary>
    12     /// 用户姓名
    13     /// </summary>
    14     public string UserName { get; set; }
    15 
    16     /// <summary>
    17     /// 性别
    18     /// </summary>
    19     public string Gender { get; set; }
    20 
    21     /// <summary>
    22     /// 身高
    23     /// </summary>
    24     public decimal Height { get; set; }
    25 
    26     /// <summary>
    27     /// 体重
    28     /// </summary>
    29     public decimal Weight { get; set; }
    30 
    31     /// <summary>
    32     /// 生日
    33     /// </summary>
    34     public DateTime Birthday { get; set; }
    35 
    36     /// <summary>
    37     /// 出生地
    38     /// </summary>
    39     public string HomeTown { get; set; }
    40 
    41     /// <summary>
    42     /// 部门
    43     /// </summary>
    44     public string Department { get; set; }
    45 
    46     /// <summary>
    47     /// 职级
    48     /// </summary>
    49     public string Level { get; set; }
    50 
    51     /// <summary>
    52     /// 用户薪资
    53     /// </summary>
    54     public decimal Salary { get; set; }
    55 
    56     /// <summary>
    57     /// 爱好
    58     /// </summary>
    59     public string Hobby { get; set; }
    60 
    61     /// <summary>
    62     /// 学历
    63     /// </summary>
    64     public string Degress = string.Empty;
    65 
    66     /// <summary>
    67     /// 年龄
    68     /// </summary>
    69     public int Age = 0;
    70 }

    再定义一个方法填充一些数据模拟DataTable,这里填充了50w条记录

    MockData
     1 /// <summary>
     2 /// 模拟数据
     3 /// </summary>
     4 /// <returns></returns>
     5 private static DataTable MockData()
     6 {
     7     DataTable dt = new DataTable("UserInfo");
     8 
     9     // 添加数据列
    10     DataColumn dc = null;
    11 
    12     dc = dt.Columns.Add("UserID", Type.GetType("System.Int32"));
    13     dc.AutoIncrement = true;    //自动增加
    14     dc.AutoIncrementSeed = 1;   //起始为1
    15     dc.AutoIncrementStep = 1;   //步长为1
    16     dc.AllowDBNull = false;
    17 
    18     dc = dt.Columns.Add("UserName", Type.GetType("System.String"));
    19     dc = dt.Columns.Add("Gender", Type.GetType("System.String"));
    20     dc = dt.Columns.Add("Height", Type.GetType("System.Decimal"));
    21     dc = dt.Columns.Add("Weight", Type.GetType("System.Decimal"));
    22     dc = dt.Columns.Add("Birthday", Type.GetType("System.DateTime"));
    23     dc = dt.Columns.Add("HomeTown", Type.GetType("System.String"));
    24     dc = dt.Columns.Add("Department", Type.GetType("System.String"));
    25     dc = dt.Columns.Add("Level", Type.GetType("System.String"));
    26     dc = dt.Columns.Add("Salary", Type.GetType("System.Decimal"));
    27     dc = dt.Columns.Add("Hobby", Type.GetType("System.String"));
    28     dc = dt.Columns.Add("Degress", Type.GetType("System.String"));
    29     dc = dt.Columns.Add("Age", Type.GetType("System.Int32"));
    30 
    31 
    32     #region 添加数据行
    33 
    34     // 方式1
    35     //DataRow dr = null;
    36 
    37     //dr = dt.NewRow();
    38     //dr["UserName"] = "洪自军";
    39     //dr["Salary"] = 123.45;
    40     //dt.Rows.Add(dr);
    41 
    42     //dr = dt.NewRow();
    43     //dr["UserName"] = "武建昌";
    44     //dr["Salary"] = 987.65;
    45     //dt.Rows.Add(dr);
    46 
    47     // 方式2
    48     //dt.Rows.Add(new object[] { null, "張洋", 123.45 });
    49     //dt.Rows.Add(new object[] { null, "張兄家", 987.65 });
    50     //dt.Rows.Add(new object[] { null, "王生杰", 111.11 });
    51     //dt.Rows.Add(new object[] { null, "呉QQ", 888.88 });
    52     //dt.Rows.Add(new object[] { null, "劉瑞", 222.22 });
    53 
    54     for (int i = 0; i < 500000; i++)
    55     {
    56         dt.Rows.Add(new object[] { 
    57             null, "测试" + i, "", 123.45, 543.21,
    58             "1990-02-14", "火星", "码农组", "码农", 250.13, "吃喝玩乐",
    59             1127963, 20
    60         });
    61     }
    62 
    63     #endregion
    64 
    65     return dt;
    66 }

    调用转换辅助类进行转换

    调用转换处理
     1 /// <summary>
     2 /// DataTable-->List测试
     3 /// </summary>
     4 private static void MockDataTableConvertToList()
     5 {
     6     // 定义时间起点
     7     TimeSpan tsStart = new TimeSpan(DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
     8 
     9     // 変換処理
    10     IList<UserInfo> users = ConvertHelper<UserInfo>.DataTableConvertToList(MockData());
    11 
    12     // 定义时间终点
    13     TimeSpan tsEnd = new TimeSpan(DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
    14 
    15     // 计算耗时
    16     TimeSpan ts = tsStart.Subtract(tsEnd).Duration();
    17 
    18     Console.WriteLine(string.Format("DataTable-->List 変換耗時:{0}", ts.ToString()));
    19 
    20     //foreach (var user in users)
    21     //{
    22     //    Console.WriteLine("{0} : {1} - {2};", user.UserID, user.UserName, user.Salary);
    23     //}
    24 }
    25 
    26 /// <summary>
    27 /// DataTable-->Json测试
    28 /// </summary>
    29 private static void MockDataTableConvertToJson()
    30 {
    31     // 定义时间起点
    32     TimeSpan tsStart = new TimeSpan(DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
    33 
    34     // 変換処理
    35     string jsonString = ConvertHelper<UserInfo>.DataTableConvertToJson(MockData());
    36 
    37     // 定义时间终点
    38     TimeSpan tsEnd = new TimeSpan(DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
    39 
    40     // 计算耗时
    41     TimeSpan ts = tsStart.Subtract(tsEnd).Duration();
    42 
    43     Console.WriteLine(string.Format("DataTable-->Json 変換耗時:{0}", ts.ToString()));
    44 
    45     //Console.WriteLine(jsonString);
    46 }

    两句代码完成

    IList<UserInfo> users = ConvertHelper<UserInfo>.DataTableConvertToList(MockData());
    
    string jsonString = ConvertHelper<UserInfo>.DataTableConvertToJson(MockData());

    可以看到转换后的效果

    前几条数据是DataTable转换为List的效果,后一条数据是DataTable转换为JSON的效果

    再贴一张类型转换时间的测试结果吧,50w条记录转换10秒左右

    是不是很简单呢?

    如果您有好的实现或是意见,别忘了告诉我哦 ^_^

  • 相关阅读:
    【bzoj2561】最小生成树 网络流最小割
    【bzoj4407】于神之怒加强版 莫比乌斯反演+线性筛
    【bzoj4816】[Sdoi2017]数字表格 莫比乌斯反演
    【bzoj3252】攻略 贪心+DFS序+线段树
    【bzoj1690】[Usaco2007 Dec]奶牛的旅行 分数规划+Spfa
    【bzoj3291】Alice与能源计划 模拟费用流+二分图最大匹配
    【bzoj2752】[HAOI2012]高速公路(road) 线段树
    wpf--- TextBlock文字设置属性
    无边框WPF窗体——允许拖动
    C# 枚举、字符串、值的相互转换
  • 原文地址:https://www.cnblogs.com/iflytek/p/2764591.html
Copyright © 2011-2022 走看看