反射和特性 自定义转换datatable为强类型集合
转换类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public static class ListGenerater { //加入DataTable扩展方法 public static List<T> ConvertToList<T>(this DataTable dt) { Type type = typeof(T); var fieldBinding = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance; //得到数据库字段名和类名的映射关系 var mappings = type.GetProperties() .Where((item) => { var attrs = item.GetCustomAttributes(typeof(DBColumnAttribute), false); return attrs.Length > 0; }) .Select((item) => { var attr = item.GetCustomAttributes(typeof(DBColumnAttribute), false)[0] as DBColumnAttribute; var dbName=(string.IsNullOrEmpty(attr.DbName) ? item.Name : attr.DbName); var storage = string.IsNullOrEmpty(attr.Storage) ? null : type.GetField(attr.Storage, fieldBinding); return new { Type = item.PropertyType, DbName = dbName, Property = item, StorageField=storage }; }); //动态生成类,根据映射关系得到datatable里的数据,再赋值到类中 List<T> list = new List<T>(); foreach (DataRow row in dt.Rows) { T temp = Activator.CreateInstance<T>(); foreach (var mapping in mappings) { if (mapping.StorageField==null) { mapping.Property.SetValue(temp, row[mapping.DbName], null); } else { mapping.StorageField.SetValue(temp, row[mapping.DbName]); } } list.Add(temp); } return list; } } [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class DBColumnAttribute : Attribute { /// <summary> /// 对应数据集中的字段名 /// </summary> public string DbName { get; set; } /// <summary> /// 存储的字段,如果设置,会绕过属性存取器,直接对字段赋值 /// </summary> public string Storage { get; set; } }
测试代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Program { static void Main(string[] args) { string constr = "Data Source=.;Initial Catalog=ShiShangDBx;Integrated Security=True"; string querystr = "select top(5) * from [User]"; SqlDataAdapter ada = new SqlDataAdapter(querystr, constr); DataTable dt = new DataTable(); ada.Fill(dt); var p = new Program(); p.TestDynamic(dt); p.TestStatic(dt); } public void TestDynamic(DataTable dt) { var watch = Stopwatch.StartNew(); watch.Start(); for (int i = 0; i < 10000; i++) { var userlist = dt.ConvertToList<UserInfo>(); } watch.Stop(); Console.WriteLine(watch.Elapsed); } public void TestStatic(DataTable dt) { var watch = Stopwatch.StartNew(); watch.Start(); for (int i = 0; i < 10000; i++) { var userlist = convert(dt); } watch.Stop(); Console.WriteLine(watch.Elapsed); } public List<UserInfo> convert(DataTable dt) { List<UserInfo> list = new List<UserInfo>(); foreach (DataRow row in dt.Rows) { var user = new UserInfo(row["ID"].ToString()) { IsAnonymous = bool.Parse(row["IsAnonymous"].ToString()), LastActiveDate = DateTime.Parse(row["LastActiveDate"].ToString()) }; } return list; } } public class UserInfo { [DBColumn(DbName = "ID", Storage = "_UserID")] public Guid UserID { get { return _UserID; } } [DBColumn] public bool IsAnonymous { get; set; } [DBColumn] public DateTime LastActiveDate { get; set; } private Guid _UserID; public UserInfo() { } public UserInfo(Guid userId) { _UserID = userId; } public UserInfo(string userId) { _UserID =Guid.Parse(userId); } }
动态反射转换和硬编码相比有虽然几倍的差距,不过对于数据交换不是很频繁的情况下,绝对时间差距还是不大的
使用这个辅助类,或者适当改造,就可以实现一般ORM的Query<T>的效果