反射实现 Data To Model
调用 :
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的更多相关文章
- 利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model
利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model 使用场景:网站配置项目,为了便于管理,网站有几个Model类来管理配置文件, 比如ConfigWebsiteMo ...
- 利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理
利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理 2018-3-10 15:18 | 发布:Admin | 分类:代码库 | 评论: ...
- 在整合spring和mongodb中,提示at org.springframework.data.mapping.model.BasicPersistentEntity.findAnnotation(
遇到这种坑,找了好多资料.基本是都是因为springdata的jar包和spring的版本不兼容导致,除了这个错误之外,还有会比较多其他错误,也是版本不兼容导致的. at org.springfram ...
- elasticsearch6.7 05. Document APIs(1)data replication model
data replication model 本节首先简要介绍Elasticsearch的data replication model,然后详细描述以下CRUD api: 1.读写文档(Reading ...
- 运用模型绑定和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 ...
- C# 反射之SqlDatareader转换为Model实体.
虽说反射的效率比较低,但是在当今的时代,盛行的大数据,以及高并发的产生,硬件的产能正在逐渐的提升,所以我们可以用空间来换取时间.反射所消耗的那些性能问题其实在企业级开发而言也就无所谓了.二 : 反射得 ...
- Metadata file not found - Data.Entity.Model
错误 3 正在编译转换: 未能找到元数据文件“F:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\..\IDE\Micr ...
- C# 利用反射动态给模型Model 赋值
https://www.cnblogs.com/waitingfor/articles/2220669.html object ff = Activator.CreateInstance(tt, nu ...
- ExtJS笔记 Ext.data.Model
A Model represents some object that your application manages. For example, one might define a Model ...
随机推荐
- C++ 头文件系列(fstream)
1. 简介 该头文定义了与文件箱关联的流类的4个模版: basic_filebuf basic_ifstream basic_ofstream basic_fstream 和8个类型: filebuf ...
- 配置IIS Express以便通过IP地址访问调试的网站
问题背景 最近使用C#编写了一个WebService,希望通过Java进行调用.使用Visual Studio 2013调试WebService时,可以在浏览器中通过localhost地址访问WSDL ...
- netflix ribbon概述
LB方案分类 目前主流的LB方案可分成两类:一种是集中式LB, 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略 ...
- Android Studio JNI开发入门教程
Android Studio JNI开发入门教程 2016-08-29 14:38 3269人阅读 评论(0) 收藏 举报 分类: JNI(3) 目录(?)[+] 概述 在Andorid ...
- Linux 下查看CPU的使用情况
1.top使用权限:所有使用者使用方式:top [-] [d delay] [q] [c] [S] [s] [i] [n] [b]说明:即时显示process的动态d :改变显示的更新速度,或是在交谈 ...
- 性能测试工具 - Apache JMeter (安装)
简介 Apache JMeter 是100%纯java语言开发的负载测试和性能测试开源工具. 功能 Apache JMeter可以对静态/动态资源进行性能测试,模拟多个用户并行请求资源端,以测试其强度 ...
- redis的数据类型 (一) 字符串
redis中存储方式是以键值对存储的,所以叫做字典试.redis(Remote dictionary server)远程字典服务器 每个redis数据类型,都会有增加.删除,查看的功能,用实例来学习命 ...
- Oracle 数据库启用归档
一.关闭数据库 二.启动数据库到mount状态 三.启用或停止归档模式 启用 停用 四.开启数据库并查看归档模式 参考文档:http://blog.csdn.net/feifei_86/article ...
- leetcode HouseRobber Dp Code
#include <malloc.h> int MAX(int x,int y){ return x>y?x:y;} int rob(int* nums, int numsSize) ...
- 模拟Struts2框架Action的实现
1.具体项目结构如下: