调用 :

  public ActionResult Index()
{
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Age");
dt.Columns.Add("RegisterTime123");
dt.Columns.Add("Last123LoginTime");
dt.Columns.Add("Active");
dt.Rows.Add("zs0", , DateTime.Now.AddDays(-), DateTime.Now, );
dt.Rows.Add("zs1", , DateTime.Now.AddDays(-), DateTime.Now, );
dt.Rows.Add("zs2", , DateTime.Now.AddDays(-), DateTime.Now, );
dt.Rows.Add("zs3", , DateTime.Now.AddDays(-), DateTime.Now, );
dt.Rows.Add("zs4", , DateTime.Now.AddDays(-), DateTime.Now, );
List<People> list = new List<People>(); //1、 不定义映射时,默认会转换属性名和列名相同的列,属性名和列名不区分大小写
list = DataToModelHelper.RefDataTableToList<People>(dt); //2、 添加自定义列名和属性名映射 默认列名和属性名相同的也会转换
ColumnPropertyMapping[] cmMaps = {
new ColumnPropertyMapping("Last123LoginTime","lastLoginTime")
,new ColumnPropertyMapping("RegisterTime123","registerTime")
};
list = DataToModelHelper.RefDataTableToList<People>(dt, cmMaps); //
//3、 DataReader 转换
string sql =
@" select userid Cuserid, username Cusername, passwordhash Cpasswordhash,
email, phonenumber, isfirsttimelogin, accessfailedcount, creationdate, isactive from cicuser ";
List<CICUser> list = null;
ColumnPropertyMapping[] cpmaps = {
new ColumnPropertyMapping("Cuserid", "userid")
,new ColumnPropertyMapping("Cusername", "username")
,new ColumnPropertyMapping("Cpasswordhash", "passwordhash")
};
using (IDataReader reader = OHelper.ExecuteReader(sql))
{
list = DataToModelHelper.RefDataReaderToList<CICUser>(reader); // 默认匹配和属性名相同的列
list = DataToModelHelper.RefDataReaderToList<CICUser>(reader,cpmaps); // 优先匹配自定义映射
} return View();
}

测试实体:

  // 测试的实体类
public class People
{
public string name { get; set; }
public int age { get; set; }
public DateTime registerTime { get; set; }
public DateTime lastLoginTime { get; set; }
public int active { get; set; }
}

Helper :

 using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks; namespace xxoo.Common
{ /** 反射实现DataTable To Model **/
// 实体转换类
public class DataToModelHelper
{ private static readonly ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>> TypeProperties = new ConcurrentDictionary<RuntimeTypeHandle, IEnumerable<PropertyInfo>>(); private static IEnumerable<PropertyInfo> TypePropertiesCache(Type type)
{
IEnumerable<PropertyInfo> pis;
if (TypeProperties.TryGetValue(type.TypeHandle, out pis))
{
return pis;
} var properties = type.GetProperties();
TypeProperties[type.TypeHandle] = properties;
return properties;
} /// <summary>
/// 通过反射实体属性名称 将DataTable转换实体集
/// 列名和属性名称不区分大小写
/// </summary>
/// <typeparam name="T">需要转换的实体类型</typeparam>
/// <param name="ds">查询的数据表</param>
/// <param name="parMaps">自定义的实体属性和DataTable列名的映射</param>
/// <returns>实体集合</returns>
public static List<T> RefDataTableToList<T>(DataTable ds, params ColumnPropertyMapping[] parMaps) where T : new()
{ List<T> list = new List<T>();
if (ds == null || ds.Rows.Count <= )
return list; // 没有数据 List<ColumnPropertyConvert<T>> rmmpList = new List<ColumnPropertyConvert<T>>(); //实体列映射集合
List<string> columnNameList = new List<string>();
// 循环获取到实体属性
foreach (DataColumn item in ds.Columns)
{ //列名转换为小写
columnNameList.Add(item.ColumnName.ToLower());
} var type = typeof(T);
var allProperties = TypePropertiesCache(type); // 读取缓存属性 if (parMaps == null || parMaps.Length == )
{ //无自定义映射,默认查找列名和属性名相同的映射
foreach (System.Reflection.PropertyInfo proInfo in allProperties)
{ // 循环实体属性集合
if (columnNameList.Contains(proInfo.Name.ToLower()))
{ //列明中包含该属性名称
ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(proInfo.Name, proInfo.Name, proInfo);
// 判断是否是可空类型
if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
map.isNullable = true;
}
rmmpList.Add(map);
}
}
}
else
{ //有自定义映射,查找默认映射同时 查找自定义映射 foreach (System.Reflection.PropertyInfo proInfo in allProperties)
{ // 循环实体属性集合
if (columnNameList.Contains(proInfo.Name.ToLower()))
{ //列明中包含该属性名称
ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(proInfo.Name, proInfo.Name, proInfo);
// 判断是否是可空类型
if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
map.isNullable = true;
}
rmmpList.Add(map);
}
else
{
foreach (ColumnPropertyMapping parMap in parMaps)
{
// 存在该属性 和 该列
if (parMap.ProertyName.ToLower() == proInfo.Name.ToLower() && columnNameList.Contains(parMap.ColumnName.ToLower()))
{
ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(parMap.ColumnName, proInfo.Name, proInfo); //列名用反射得到的准确
// 判断是否是可空类型
if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
map.isNullable = true;
}
rmmpList.Add(map);
}
}
}
}
} if (rmmpList.Count == ) return list; // 没有列名和属性名的映射 // 装载实体数据
foreach (DataRow row in ds.Rows)
{
T t = new T();
foreach (ColumnPropertyConvert<T> map in rmmpList)
{
try
{
map.ParseValue(t, map.ProInfo, row[map.ColumnName]);
}
catch { continue; }
} list.Add(t);
}//foreach datarow
return list;
} /// <summary>
/// 通过反射实体属性名称 将DataTable转换实体集
/// 列名和属性名称不区分大小写
/// </summary>
/// <typeparam name="T">需要转换的实体类型</typeparam>
/// <param name="ds">查询的数据表</param>
/// <param name="parMaps">自定义的实体属性和DataReader列名的映射</param>
/// <returns>实体集合</returns>
public static List<T> RefDataReaderToList<T>(IDataReader dr, params ColumnPropertyMapping[] parMaps) where T : new()
{ List<T> list = new List<T>();
if (dr == null)
return list; // 没有数据 List<ColumnPropertyConvert<T>> rmmpList = new List<ColumnPropertyConvert<T>>(); //实体列映射集合
List<string> columnNameList = new List<string>();
int fieldCount = dr.FieldCount;
for (int i = ; i < fieldCount; i++)
{
columnNameList.Add(dr.GetName(i).ToLower());
} #region 配置实体属性和列名映射
var type = typeof(T);
var allProperties = TypePropertiesCache(type); // 读取缓存属性 if (parMaps == null || parMaps.Length == )
{ //无自定义映射,默认查找列名和属性名相同的映射
foreach (System.Reflection.PropertyInfo proInfo in allProperties)
{ // 循环实体属性集合
if (columnNameList.Contains(proInfo.Name.ToLower()))
{ //列明中包含该属性名称
ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(proInfo.Name, proInfo.Name, proInfo);
// 判断是否是可空类型
if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
map.isNullable = true;
rmmpList.Add(map);
}
}
}
else
{ //有自定义映射,查找默认映射同时 查找自定义映射 foreach (System.Reflection.PropertyInfo proInfo in allProperties)
{ // 循环实体属性集合
if (columnNameList.Contains(proInfo.Name.ToLower()))
{ //列明中包含该属性名称
ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(proInfo.Name, proInfo.Name, proInfo);
// 判断是否是可空类型
if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
map.isNullable = true;
rmmpList.Add(map);
}
else
{
foreach (ColumnPropertyMapping parMap in parMaps)
{
// 存在该属性 和 该列
if (parMap.ProertyName.ToLower() == proInfo.Name.ToLower() && columnNameList.Contains(parMap.ColumnName.ToLower()))
{
ColumnPropertyConvert<T> map = new ColumnPropertyConvert<T>(parMap.ColumnName, proInfo.Name, proInfo); //列名用反射得到的准确
// 判断是否是可空类型
if (proInfo.PropertyType.IsGenericType && proInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
map.isNullable = true;
rmmpList.Add(map);
}
}
}
}
}
#endregion if (rmmpList.Count == ) return list; // 没有列名和属性名的映射 // 装载实体数据
while (dr.Read())
{
T t = new T();
foreach (ColumnPropertyConvert<T> map in rmmpList)
{
try
{
map.ParseValue(t, map.ProInfo, dr[map.ColumnName]);
}
catch { continue; }
} list.Add(t);
}
dr.Close();
dr.Dispose(); return list;
} }
/// <summary>
/// 自定义映射类
/// </summary>
public class ColumnPropertyMapping
{
/// <summary>
/// 列名与实体属性名的映射
/// </summary>
/// <param name="columnName">列名</param>
/// <param name="proertyName">属性名称</param>
public ColumnPropertyMapping(string columnName, string proertyName)
{
this.ColumnName = columnName;
this.ProertyName = proertyName;
}
public string ColumnName { get; set; }
public string ProertyName { get; set; }
}
/// <summary>
/// 属性列名数据转换器器
/// </summary>
/// <typeparam name="T"></typeparam>
public class ColumnPropertyConvert<T> where T : new()
{
public ColumnPropertyConvert(string columnName, string proertyName, System.Reflection.PropertyInfo proInfo)
{
this.ColumnName = columnName;
this.ProertyName = proertyName;
this.ProInfo = proInfo;
isNullable = false; this.ParseValue = (t, m, o) =>
{ if (!isNullable)
{
this.ProInfo.SetValue(t, Convert.ChangeType(o, this.ProInfo.PropertyType), null);
}
else { // 可空类型
this.ProInfo.SetValue(t, Convert.ChangeType(o, Nullable.GetUnderlyingType(m.PropertyType)), null);
}
};
#region 注释
//switch (this.ProInfo.PropertyType.ToString())
//{
// case "System.Int32":
// this.ParseValue = (t, m, o) =>
// { // this.ProInfo.SetValue(t, int.Parse(o.ToString()), null);
// };
// break;
// case "System.Boolean":
// this.ParseValue = (t, m, o) =>
// {
// this.ProInfo.SetValue(t, bool.Parse(o.ToString()), null);
// };
// break;
// case "System.String":
// this.ParseValue = (t, m, o) =>
// {
// this.ProInfo.SetValue(t, o.ToString(), null);
// };
// break;
// case "System.DateTime":
// this.ParseValue = (t, m, o) =>
// {
// this.ProInfo.SetValue(t, DateTime.Parse(o.ToString()), null);
// };
// break;
// case "System.Decimal":
// this.ParseValue = (t, m, o) =>
// {
// this.ProInfo.SetValue(t, decimal.Parse(o.ToString()), null);
// };
// break;
// case "System.Guid":
// this.ParseValue = (t, m, o) =>
// {
// this.ProInfo.SetValue(t, Guid.Parse(o.ToString()), null);
// };
// break;
// default:
// break;
//}//swicth
#endregion
} public bool isNullable { get; set; }
public string ColumnName { get; set; }
public string ProertyName { get; set; }
public System.Reflection.PropertyInfo ProInfo { get; set; }
// "System.Int32":"System.Boolean":"System.String":"System.DateTime":"System.Decimal":"System.Guid": public Action<T, System.Reflection.PropertyInfo, object> ParseValue;
}
}

反射实现 Data To Model的更多相关文章

  1. 利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model

    利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model   使用场景:网站配置项目,为了便于管理,网站有几个Model类来管理配置文件, 比如ConfigWebsiteMo ...

  2. 利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理

    利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理   2018-3-10 15:18 | 发布:Admin | 分类:代码库 | 评论: ...

  3. 在整合spring和mongodb中,提示at org.springframework.data.mapping.model.BasicPersistentEntity.findAnnotation(

    遇到这种坑,找了好多资料.基本是都是因为springdata的jar包和spring的版本不兼容导致,除了这个错误之外,还有会比较多其他错误,也是版本不兼容导致的. at org.springfram ...

  4. elasticsearch6.7 05. Document APIs(1)data replication model

    data replication model 本节首先简要介绍Elasticsearch的data replication model,然后详细描述以下CRUD api: 1.读写文档(Reading ...

  5. 运用模型绑定和web窗体显示和检索数据(Retrieving and displaying data with model binding and web forms)

    原文 http://www.asp.net/web-forms/overview/presenting-and-managing-data/model-binding/retrieving-data ...

  6. C# 反射之SqlDatareader转换为Model实体.

    虽说反射的效率比较低,但是在当今的时代,盛行的大数据,以及高并发的产生,硬件的产能正在逐渐的提升,所以我们可以用空间来换取时间.反射所消耗的那些性能问题其实在企业级开发而言也就无所谓了.二 : 反射得 ...

  7. Metadata file not found - Data.Entity.Model

    错误 3 正在编译转换: 未能找到元数据文件“F:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\..\IDE\Micr ...

  8. C# 利用反射动态给模型Model 赋值

    https://www.cnblogs.com/waitingfor/articles/2220669.html object ff = Activator.CreateInstance(tt, nu ...

  9. ExtJS笔记 Ext.data.Model

    A Model represents some object that your application manages. For example, one might define a Model ...

随机推荐

  1. supervisor踩坑记录

    线上一直以来都在用supervisor管理各项服务,感觉非常舒心,supervisor管理`gunicorn`和`celery`进程,web服务和异步任务各司其职,跑起来一直很稳定. 前段时间却不小心 ...

  2. AJSX 传输数组

    如果要利用ajax传输数组,或者传输多个(不知道有多少个)class的某一属性的值,例如: 要将这三个数据传入php编辑界面,图片显示有三个数据,但实际上,数据的多少是由数据库所导出的数据 决定的.如 ...

  3. 国内不能使用Google解决方案(不断更新与递增中...)

    1.修改hosts方式可以根据对hosts的配置,解决Google搜索.Gmail.谷歌学术.维基百科.GitHub.Twitter.Facebook.Flickr.imgur.Google Serv ...

  4. php编译安装

    php编译安装含mcrypt扩展 开始前准备 1.php源码下载 这里用的是php5.6.22版本 wget -c http://cn2.php.net/get/php-5.6.22.tar.gz/f ...

  5. BZOJ1115:[POI2009]石子游戏Kam (博弈论)

    挺水的 听说是阶梯nim和,就去看了一下,然后就会了= = 观察题目,发现拿第i堆棋子k个造成的影响就是第i+1堆棋子能多拿k个 可以把模型转化为,有n堆石子,每次从某一堆拿一个石子,放在下一堆中,不 ...

  6. windows管道

    匿名管道的使用 匿名管道主要用于本地父进程和子进程之间的通信, 在父进程中的话,首先是要创建一个匿名管道, 在创建匿名管道成功后,可以获取到对这个匿名管道的读写句柄, 然后父进程就可以向这个匿名管道中 ...

  7. 【openstack N版】——镜像服务glance

    一.openstack镜像服务glance 1.1 glance介绍 glance主要是由三部分组成 glance-api:接收云系统镜像的创建,删除,读取请求,类似nova-api,通过其他模块(g ...

  8. 360浏览器和猎豹浏览器重定向后丢失get参数

    1.场景: step1: 用户请求项目 http://localhost:8080/myProject step2: 我们的服务器将请求重定向到一个静态页面,并拼接上部分参数,如: <%@ pa ...

  9. 【转载】JavaScript继承详解(二)

    这一章我们将会重点介绍JavaScript中几个重要的属性(this.constructor.prototype), 这些属性对于我们理解如何实现JavaScript中的类和继承起着至关重要的作用. ...

  10. 项目架构开发:数据访问层之UnitOfWork

    接上文 项目架构开发:数据访问层之IQuery 本章我们继续IUnitOfWork的开发,从之前的IRepository接口中就可以看出,我们并没有处理单元事务, 数据CUD每次都是立即执行的,这样有 ...