反射和特性 自定义转换datatable为强类型集合

 转换类:

View Code
   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; }
    }

测试代码:

View Code
    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>的效果

原文地址:https://www.cnblogs.com/FlyCat/p/2613205.html