反射和特性 自定义转换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>的效果

你可能感兴趣的:(Datatable)