将DataTable数据转化为Model对象列表

最近做项目实现了自动将DataTable对象中的数据转化为制定Model类型对象列表的功能,这里做记录:

因为开发过程中往往是要分层的,所以经常要将从数据库中查询出来的数据转变成为对象形式,所以在这里定义了一个ModelConvertor类,用于将从数据库查询出来的表形式数据转化为模型层对象,为了增加通用性,这里使用了泛型,当需要将数据转化为制定Model列表时,只需要加上泛型参数即可。

首先是定义转化类 :

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Linq;
  6 using System.Reflection;
  7 using System.Text;
  8 using System.Threading.Tasks;
  9 
 10 namespace ClassView
 11 {
 12     /// <summary>
 13     ///     进行从 DataTable 或者实现 IDataReader 接口的对象读取记录
 14     ///     并将结果集转换为给定类型列表的方法。
 15     /// </summary>
 16     public class ModelConvetor
 17     {
 18         /// <summary>
 19         ///     从 reader 对象中逐行读取记录并将记录转化为 T 类型的集合
 20         /// </summary>
 21         /// <typeparam name="T">目标类型参数</typeparam>
 22         /// <param name="reader">实现 IDataReader 接口的对象。</param>
 23         /// <returns>指定类型的对象集合。</returns>
 24         public static List<T> ConvertToObject<T>(IDataReader reader)
 25             where T : class
 26         {
 27             List<T> list = new List<T>();
 28             T obj = default(T);
 29             Type t = typeof(T);
 30             Assembly ass = t.Assembly;
 31 
 32             Dictionary<string, PropertyInfo> propertys = ModelConvetor.GetFields<T>(reader);
 33             PropertyInfo p = null;
 34             if (reader != null)
 35             {
 36                 while (reader.Read())
 37                 {
 38                     obj = ass.CreateInstance(t.FullName) as T;
 39                     foreach (string key in propertys.Keys)
 40                     {
 41                         p = propertys[key];
 42                         p.SetValue(obj, ModelConvetor.ChangeType(reader[key], p.PropertyType));
 43                     }
 44                     list.Add(obj);
 45                 }
 46             }
 47 
 48             return list;
 49         }
 50 
 51         /// <summary>
 52         ///     从 DataTale 对象中逐行读取记录并将记录转化为 T 类型的集合
 53         /// </summary>
 54         /// <typeparam name="T">目标类型参数</typeparam>
 55         /// <param name="reader">DataTale 对象。</param>
 56         /// <returns>指定类型的对象集合。</returns>
 57         public static List<T> ConvertToObject<T>(DataTable table)
 58             where T : class
 59         {
 60             return table == null
 61                 ? new List<T>()
 62                 : ModelConvetor.ConvertToObject<T>(table.CreateDataReader() as IDataReader);
 63         }
 64 
 65         /// <summary>
 66         ///     将数据转化为 type 类型
 67         /// </summary>
 68         /// <param name="value">要转化的值</param>
 69         /// <param name="type">目标类型</param>
 70         /// <returns>转化为目标类型的 Object 对象</returns>
 71         private static object ChangeType(object value, Type type)
 72         {
 73             if (type.FullName == typeof(string).FullName)
 74             {
 75                 return Convert.ChangeType(Convert.IsDBNull(value) ? null : value, type);
 76             }
 77             if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
 78             {
 79                 NullableConverter convertor = new NullableConverter(type);
 80                 return Convert.IsDBNull(value) ? null : convertor.ConvertFrom(value);
 81             }
 82             return value;
 83         }
 84 
 85         /// <summary>
 86         ///     获取reader存在并且在 T 类中包含同名可写属性的集合
 87         /// </summary>
 88         /// <param name="reader">
 89         ///     可写域的集合
 90         /// </param>
 91         /// <returns>
 92         ///     以属性名为键,PropertyInfo 为值得字典对象
 93         /// </returns>
 94         private static Dictionary<string, PropertyInfo> GetFields<T>(IDataReader reader)
 95         {
 96             Dictionary<string, PropertyInfo> result = new Dictionary<string, PropertyInfo>();
 97             int columnCount = reader.FieldCount;
 98             Type t = typeof(T);
 99 
100             PropertyInfo[] properties = t.GetProperties();
101             if (properties != null)
102             {
103                 List<string> readerFields = new List<string>();
104                 for (int i = 0; i < columnCount; i++)
105                 {
106                     readerFields.Add(reader.GetName(i));
107                 }
108                 IEnumerable<PropertyInfo> resList =
109                     (from PropertyInfo prop in properties
110                      where prop.CanWrite && readerFields.Contains(prop.Name)
111                      select prop);
112 
113                 foreach (PropertyInfo p in resList)
114                 {
115                     result.Add(p.Name, p);
116                 }
117             }
118             return result;
119         }
120     }
121 }

接下来是测试类型:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace ClassView
 8 {
 9     public class TestObj
10     {
11         public int? UserID { get; set; }
12         public string UserName { get; set; }
13         public decimal? Height { get; set; }
14         public DateTime? Birthday { get; set; }
15     }
16 }

最后是测试代码:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Data;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7 
 8 namespace ClassView
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             DataTable table = new DataTable();
15             table.Columns.AddRange(new DataColumn[]
16                 {
17                     new DataColumn("UserID"),
18                     new DataColumn("UserName"),
19                     new DataColumn("Height"),
20                     new DataColumn("Birthday")
21                 });
22             for (int i = 0; i < 10; i++)
23             {
24                 DataRow row = table.NewRow();
25                 row["UserID"] = i % 2 == 0 ? DBNull.Value : i as object;
26                 row["UserName"] = "User" + i;
27                 row["Height"] = i % 5 == 0 ? DBNull.Value : (i + 5) as object;
28                 row["Birthday"] = i % 3 == 0 ? DBNull.Value : (DateTime.Now) as object;
29                 table.Rows.Add(row);
30             }
31             List<TestObj> res = ModelConvetor.ConvertToObject<TestObj>(table);
32             foreach (TestObj o in res)
33             {
34                 Console.WriteLine(string.Format("UserID:{0}",o.UserID));
35                 Console.WriteLine(string.Format("UserName:{0}", o.UserName));
36                 Console.WriteLine(string.Format("Height:{0}", o.Height));
37                 Console.WriteLine(string.Format("Birthday:{0}", o.Birthday));
38                 Console.WriteLine("-------------------------------------------------------------------------");
39             }
40             Console.ReadLine();
41         }
42     }
43 }

执行结果如下:

 

 

下次是配置数据库代码,to be continue ...

posted @ 2014-11-01 19:00  plle  阅读(3843)  评论(3编辑  收藏  举报