zoukankan      html  css  js  c++  java
  • 反射实现 Data To Model

    调用 : 

     1  public ActionResult Index()
     2         {   
     3             DataTable dt = new DataTable();
     4             dt.Columns.Add("Name");
     5             dt.Columns.Add("Age");
     6             dt.Columns.Add("RegisterTime123");
     7             dt.Columns.Add("Last123LoginTime");
     8             dt.Columns.Add("Active");
     9             dt.Rows.Add("zs0", 0, DateTime.Now.AddDays(-0), DateTime.Now, 1);
    10             dt.Rows.Add("zs1", 1, DateTime.Now.AddDays(-1), DateTime.Now, 1);
    11             dt.Rows.Add("zs2", 2, DateTime.Now.AddDays(-2), DateTime.Now, 1);
    12             dt.Rows.Add("zs3", 3, DateTime.Now.AddDays(-3), DateTime.Now, 1);
    13             dt.Rows.Add("zs4", 4, DateTime.Now.AddDays(-4), DateTime.Now, 1); 
    14             List<People> list = new List<People>();
    15 
    16             //1、 不定义映射时,默认会转换属性名和列名相同的列,属性名和列名不区分大小写
    17             list = DataToModelHelper.RefDataTableToList<People>(dt);
    18         
    19             //2、 添加自定义列名和属性名映射 默认列名和属性名相同的也会转换
    20             ColumnPropertyMapping[] cmMaps = {
    21                        new ColumnPropertyMapping("Last123LoginTime","lastLoginTime")  
    22                        ,new ColumnPropertyMapping("RegisterTime123","registerTime")                                         
    23                                           };
    24             list = DataToModelHelper.RefDataTableToList<People>(dt, cmMaps);
    25 
    26             // 
    27             //3、 DataReader 转换
    28             string sql =
    29 @"  select userid Cuserid,  username Cusername,  passwordhash Cpasswordhash, 
    30         email,  phonenumber,  isfirsttimelogin,  accessfailedcount,  creationdate,  isactive from cicuser ";
    31             List<CICUser> list = null;
    32             ColumnPropertyMapping[] cpmaps = {
    33                 new ColumnPropertyMapping("Cuserid", "userid")
    34                ,new ColumnPropertyMapping("Cusername", "username")
    35                ,new ColumnPropertyMapping("Cpasswordhash", "passwordhash")
    36             };
    37             using (IDataReader reader = OHelper.ExecuteReader(sql))
    38             {
    39                 list = DataToModelHelper.RefDataReaderToList<CICUser>(reader); // 默认匹配和属性名相同的列
    40                 list = DataToModelHelper.RefDataReaderToList<CICUser>(reader,cpmaps); // 优先匹配自定义映射
    41             }
    42 
    43 
    44 
    45             return View();
    46         }

    测试实体: 

    1  // 测试的实体类
    2         public class People
    3         {
    4             public string name { get; set; }
    5             public int age { get; set; }
    6             public DateTime registerTime { get; set; }
    7             public DateTime lastLoginTime { get; set; }
    8             public int active { get; set; }
    9         } 

    Helper :

      1 using System;
      2 using System.Collections.Concurrent;
      3 using System.Collections.Generic;
      4 using System.Data;
      5 using System.Linq;
      6 using System.Reflection;
      7 using System.Text;
      8 using System.Threading.Tasks;
      9 
     10 namespace xxoo.Common
     11 {
     12 
     13     /** 反射实现DataTable To Model **/
     14     // 实体转换类
     15     public class DataToModelHelper
     16     {
     17 
     18         private static readonly ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>> TypeProperties = new ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>>();
     19 
     20         private static IEnumerable<PropertyInfo> TypePropertiesCache(Type type)
     21         {
     22             IEnumerable<PropertyInfo> pis;
     23             if (TypeProperties.TryGetValue(type.TypeHandle, out pis))
     24             {
     25                 return pis;
     26             }
     27 
     28             var properties = type.GetProperties(); 
     29             TypeProperties[type.TypeHandle] = properties;
     30             return properties;
     31         }
     32 
     33 
     34 
     35         /// <summary>
     36         /// 通过反射实体属性名称 将DataTable转换实体集
     37         /// 列名和属性名称不区分大小写
     38         /// </summary>
     39         /// <typeparam name="T">需要转换的实体类型</typeparam>
     40         /// <param name="ds">查询的数据表</param>
     41         /// <param name="parMaps">自定义的实体属性和DataTable列名的映射</param>
     42         /// <returns>实体集合</returns>
     43         public static List<T> RefDataTableToList<T>(DataTable ds, params ColumnPropertyMapping[] parMaps) where T : new()
     44         {
     45 
     46             List<T> list = new List<T>();
     47             if (ds == null || ds.Rows.Count <= 0)
     48                 return list; // 没有数据
     49 
     50             List<ColumnPropertyConvert<T>> rmmpList = new List<ColumnPropertyConvert<T>>(); //实体列映射集合
     51             List<string> columnNameList = new List<string>();
     52             // 循环获取到实体属性
     53             foreach (DataColumn item in ds.Columns)
     54             { //列名转换为小写
     55                 columnNameList.Add(item.ColumnName.ToLower());
     56             }
     57 
     58             var type = typeof(T);
     59             var allProperties = TypePropertiesCache(type); // 读取缓存属性
     60 
     61             if (parMaps == null || parMaps.Length == 0)
     62             { //无自定义映射,默认查找列名和属性名相同的映射
     63                 foreach (System.Reflection.PropertyInfo proInfo in allProperties)
     64                 { // 循环实体属性集合
     65                     if (columnNameList.Contains(proInfo.Name.ToLower()))
     66                     { //列明中包含该属性名称
     67                         ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(proInfo.Name, proInfo.Name, proInfo);
     68                         // 判断是否是可空类型
     69                         if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
     70                         {
     71                             map.isNullable = true;
     72                         }
     73                         rmmpList.Add(map);
     74                     }
     75                 }
     76             }
     77             else
     78             { //有自定义映射,查找默认映射同时 查找自定义映射 
     79 
     80                 foreach (System.Reflection.PropertyInfo proInfo in allProperties)
     81                 { // 循环实体属性集合
     82                     if (columnNameList.Contains(proInfo.Name.ToLower()))
     83                     { //列明中包含该属性名称
     84                         ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(proInfo.Name, proInfo.Name, proInfo);
     85                         // 判断是否是可空类型
     86                         if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
     87                         {
     88                             map.isNullable = true;
     89                         }
     90                         rmmpList.Add(map);
     91                     }
     92                     else
     93                     {
     94                         foreach (ColumnPropertyMapping parMap in parMaps)
     95                         {
     96                             // 存在该属性 和 该列
     97                             if (parMap.ProertyName.ToLower() == proInfo.Name.ToLower() && columnNameList.Contains(parMap.ColumnName.ToLower()))
     98                             {
     99                                 ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(parMap.ColumnName, proInfo.Name, proInfo); //列名用反射得到的准确
    100                                 // 判断是否是可空类型
    101                                 if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
    102                                 {
    103                                     map.isNullable = true;
    104                                 }
    105                                 rmmpList.Add(map);
    106                             }
    107                         }
    108                     }
    109                 }
    110             }
    111 
    112             if (rmmpList.Count == 0) return list; // 没有列名和属性名的映射
    113 
    114             // 装载实体数据
    115             foreach (DataRow row in ds.Rows)
    116             {
    117                 T t = new T();
    118                 foreach (ColumnPropertyConvert<T> map in rmmpList)
    119                 {
    120                     try
    121                     {
    122                         map.ParseValue(t, map.ProInfo, row[map.ColumnName]);
    123                     }
    124                     catch { continue; }
    125                 }
    126 
    127                 list.Add(t);
    128             }//foreach datarow
    129             return list;
    130         }
    131 
    132 
    133 
    134         /// <summary>
    135         /// 通过反射实体属性名称 将DataTable转换实体集
    136         /// 列名和属性名称不区分大小写
    137         /// </summary>
    138         /// <typeparam name="T">需要转换的实体类型</typeparam>
    139         /// <param name="ds">查询的数据表</param>
    140         /// <param name="parMaps">自定义的实体属性和DataReader列名的映射</param>
    141         /// <returns>实体集合</returns>
    142         public static List<T> RefDataReaderToList<T>(IDataReader dr, params ColumnPropertyMapping[] parMaps) where T : new()
    143         {
    144 
    145             List<T> list = new List<T>();
    146             if (dr == null)
    147                 return list; // 没有数据
    148 
    149             List<ColumnPropertyConvert<T>> rmmpList = new List<ColumnPropertyConvert<T>>(); //实体列映射集合
    150             List<string> columnNameList = new List<string>();
    151             int fieldCount = dr.FieldCount;
    152             for (int i = 0; i < fieldCount; i++)
    153             {
    154                 columnNameList.Add(dr.GetName(i).ToLower());
    155             }
    156 
    157 
    158             #region 配置实体属性和列名映射
    159             var type = typeof(T);
    160             var allProperties = TypePropertiesCache(type); // 读取缓存属性
    161 
    162             if (parMaps == null || parMaps.Length == 0)
    163             { //无自定义映射,默认查找列名和属性名相同的映射
    164                 foreach (System.Reflection.PropertyInfo proInfo in allProperties)
    165                 { // 循环实体属性集合
    166                     if (columnNameList.Contains(proInfo.Name.ToLower()))
    167                     { //列明中包含该属性名称
    168                         ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(proInfo.Name, proInfo.Name, proInfo);
    169                         // 判断是否是可空类型
    170                         if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
    171                             map.isNullable = true;
    172                         rmmpList.Add(map);
    173                     }
    174                 }
    175             }
    176             else
    177             { //有自定义映射,查找默认映射同时 查找自定义映射 
    178 
    179                 foreach (System.Reflection.PropertyInfo proInfo in allProperties)
    180                 { // 循环实体属性集合
    181                     if (columnNameList.Contains(proInfo.Name.ToLower()))
    182                     { //列明中包含该属性名称
    183                         ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(proInfo.Name, proInfo.Name, proInfo);
    184                         // 判断是否是可空类型
    185                         if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
    186                             map.isNullable = true;
    187                         rmmpList.Add(map);
    188                     }
    189                     else
    190                     {
    191                         foreach (ColumnPropertyMapping parMap in parMaps)
    192                         {
    193                             // 存在该属性 和 该列
    194                             if (parMap.ProertyName.ToLower() == proInfo.Name.ToLower() && columnNameList.Contains(parMap.ColumnName.ToLower()))
    195                             {
    196                                 ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(parMap.ColumnName, proInfo.Name, proInfo); //列名用反射得到的准确
    197                                 // 判断是否是可空类型
    198                                 if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
    199                                     map.isNullable = true;
    200                                 rmmpList.Add(map);
    201                             }
    202                         }
    203                     }
    204                 }
    205             } 
    206             #endregion
    207 
    208             if (rmmpList.Count == 0) return list; // 没有列名和属性名的映射
    209             
    210             // 装载实体数据
    211             while (dr.Read())
    212             {
    213                 T t = new T();
    214                 foreach (ColumnPropertyConvert<T> map in rmmpList)
    215                 {
    216                     try
    217                     {
    218                         map.ParseValue(t, map.ProInfo, dr[map.ColumnName]);
    219                     }
    220                     catch { continue; }
    221                 }
    222 
    223                 list.Add(t);
    224             }
    225             dr.Close();
    226             dr.Dispose();
    227 
    228             return list;
    229         }
    230 
    231 
    232     }
    233     /// <summary>
    234     /// 自定义映射类
    235     /// </summary>
    236     public class ColumnPropertyMapping
    237     {
    238         /// <summary>
    239         /// 列名与实体属性名的映射
    240         /// </summary>
    241         /// <param name="columnName">列名</param>
    242         /// <param name="proertyName">属性名称</param>
    243         public ColumnPropertyMapping(string columnName, string proertyName)
    244         {
    245             this.ColumnName = columnName;
    246             this.ProertyName = proertyName;
    247         }
    248         public string ColumnName { get; set; }
    249         public string ProertyName { get; set; }
    250     }
    251     /// <summary>
    252     /// 属性列名数据转换器器
    253     /// </summary>
    254     /// <typeparam name="T"></typeparam>
    255     public class ColumnPropertyConvert<T> where T : new()
    256     {
    257         public ColumnPropertyConvert(string columnName, string proertyName, System.Reflection.PropertyInfo proInfo)
    258         {
    259             this.ColumnName = columnName;
    260             this.ProertyName = proertyName;
    261             this.ProInfo = proInfo;
    262             isNullable = false;
    263 
    264             this.ParseValue = (t, m, o) =>
    265                   {
    266 
    267                       if (!isNullable)
    268                       {
    269                           this.ProInfo.SetValue(t, Convert.ChangeType(o, this.ProInfo.PropertyType), null);
    270                       }
    271                       else { // 可空类型
    272                           this.ProInfo.SetValue(t, Convert.ChangeType(o, Nullable.GetUnderlyingType(m.PropertyType)), null);
    273                       }
    274                   };
    275             #region 注释
    276             //switch (this.ProInfo.PropertyType.ToString())
    277             //{
    278             //    case "System.Int32":
    279             //        this.ParseValue = (t, m, o) =>
    280             //        {
    281 
    282             //            this.ProInfo.SetValue(t, int.Parse(o.ToString()), null);
    283             //        };
    284             //        break;
    285             //    case "System.Boolean":
    286             //        this.ParseValue = (t, m, o) =>
    287             //        {
    288             //            this.ProInfo.SetValue(t, bool.Parse(o.ToString()), null);
    289             //        };
    290             //        break;
    291             //    case "System.String":
    292             //        this.ParseValue = (t, m, o) =>
    293             //        {
    294             //            this.ProInfo.SetValue(t, o.ToString(), null);
    295             //        };
    296             //        break;
    297             //    case "System.DateTime":
    298             //        this.ParseValue = (t, m, o) =>
    299             //        {
    300             //            this.ProInfo.SetValue(t, DateTime.Parse(o.ToString()), null);
    301             //        };
    302             //        break;
    303             //    case "System.Decimal":
    304             //        this.ParseValue = (t, m, o) =>
    305             //        {
    306             //            this.ProInfo.SetValue(t, decimal.Parse(o.ToString()), null);
    307             //        };
    308             //        break;
    309             //    case "System.Guid":
    310             //        this.ParseValue = (t, m, o) =>
    311             //        {
    312             //            this.ProInfo.SetValue(t, Guid.Parse(o.ToString()), null);
    313             //        };
    314             //        break;
    315             //    default:
    316             //        break;
    317             //}//swicth 
    318             #endregion
    319         }
    320 
    321         public bool isNullable { get; set; }
    322         public string ColumnName { get; set; }
    323         public string ProertyName { get; set; }
    324         public System.Reflection.PropertyInfo ProInfo { get; set; }
    325         // "System.Int32":"System.Boolean":"System.String":"System.DateTime":"System.Decimal":"System.Guid":
    326 
    327         public Action<T, System.Reflection.PropertyInfo, object> ParseValue;
    328     }
    329 }
        
  • 相关阅读:
    JavaScript技巧45招(转)
    css3毛玻璃效果白边问题
    css3兼容性问题归纳
    H5页面JS调试
    js操作cookie的函数
    webkit webApp 开发技术要点总结【转】
    Android如何避免输入法弹出时遮挡住按钮或输入框
    Git使用问题汇总
    Known快速开发框架
    Visual Studio 常用快捷键
  • 原文地址:https://www.cnblogs.com/cl-blogs/p/6656710.html
Copyright © 2011-2022 走看看