ExpressionMapper代码

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks; namespace LiteSql
{
/// <summary>
/// IDataRecord到实体类的映射
/// </summary>
internal class ExpressionMapper
{
#region 变量
/// <summary>
/// 缓存
/// </summary>
private static ConcurrentDictionary<string, object> _cacheDict = new ConcurrentDictionary<string, object>();
#endregion #region BindData<T> 数据绑定
/// <summary>
/// 数据绑定
/// </summary>
public static Func<IDataRecord, T> BindData<T>(PropertyInfoEx[] propertyInfoList, Dictionary<string, int> fields, Dictionary<string, Type> fieldTypes, string strFields)
{
Type entityType = typeof(T);
string key = entityType.FullName + "_" + strFields + "_T"; if (_cacheDict.TryGetValue(key, out _))
{
return _cacheDict[key] as Func<IDataRecord, T>;
}
else
{
CreateBindings(entityType, propertyInfoList, fields, fieldTypes, out ParameterExpression dataRecordExpr, out Expression initExpr); Expression<Func<IDataRecord, T>> lambda = Expression.Lambda<Func<IDataRecord, T>>(initExpr, dataRecordExpr); var func = lambda.Compile();
_cacheDict.TryAdd(key, func);
return func;
} }
#endregion #region BindData 数据绑定
/// <summary>
/// 数据绑定
/// </summary>
public static Func<IDataRecord, object> BindData(Type entityType, PropertyInfoEx[] propertyInfoList, Dictionary<string, int> fields, Dictionary<string, Type> fieldTypes, string strFields)
{
string key = entityType.FullName + "_" + strFields + "_Type";
if (_cacheDict.TryGetValue(key, out _))
{
return _cacheDict[key] as Func<IDataRecord, object>;
}
else
{
CreateBindings(entityType, propertyInfoList, fields, fieldTypes, out ParameterExpression dataRecordExpr, out Expression initExpr); Expression<Func<IDataRecord, object>> lambda = Expression.Lambda<Func<IDataRecord, object>>(initExpr, dataRecordExpr); var func = lambda.Compile();
_cacheDict.TryAdd(key, func);
return func;
} }
#endregion #region CreateBindings 属性绑定
/// <summary>
/// 属性绑定
/// </summary>
private static void CreateBindings(Type entityType, PropertyInfoEx[] propertyInfoList, Dictionary<string, int> fields, Dictionary<string, Type> fieldTypes, out ParameterExpression dataRecordExpr, out Expression initExpr)
{
dataRecordExpr = Expression.Parameter(typeof(IDataRecord), "r"); List<MemberBinding> bindings = new List<MemberBinding>(); foreach (PropertyInfoEx propertyInfoEx in propertyInfoList)
{
if (!fields.ContainsKey(propertyInfoEx.FieldNameUpper)) continue; Expression propertyValue = GetMethodCall(dataRecordExpr, propertyInfoEx, fields[propertyInfoEx.FieldNameUpper], fieldTypes[propertyInfoEx.FieldNameUpper]); MemberBinding binding = Expression.Bind(propertyInfoEx.PropertyInfo, propertyValue);
bindings.Add(binding);
} initExpr = Expression.MemberInit(Expression.New(entityType), bindings);
}
#endregion #region GetMethodCall
private static Expression GetMethodCall(ParameterExpression dataRecordExpr, PropertyInfoEx propertyInfoEx, int fieldIndex, Type fieldType)
{
Type propertyType = propertyInfoEx.PropertyInfo.PropertyType;
Type typeIDataRecord = typeof(IDataRecord); string methodName = GetIDataRecordMethod(ref fieldType); MethodCallExpression getValueExpr = Expression.Call(dataRecordExpr, typeIDataRecord.GetMethod(methodName), Expression.Constant(fieldIndex)); MethodCallExpression isDBNullExpr = Expression.Call(dataRecordExpr, typeIDataRecord.GetMethod("IsDBNull"), Expression.Constant(fieldIndex)); var convertExpr = GetConvertExpr(propertyType, fieldType, getValueExpr); return Expression.Condition(isDBNullExpr, Expression.Default(propertyType), convertExpr);
}
#endregion #region GetConvertExpr
private static Expression GetConvertExpr(Type propertyType, Type fieldType, Expression getValueExpr)
{
Expression convertExpr = null; Type genericType = null;
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
genericType = propertyType.GenericTypeArguments[0];
} string methodName = GetConvertMethod(propertyType, out Type methodReturnType); if (propertyType != fieldType)
{
if (genericType != null)
{
if (genericType == typeof(Guid))
{
Expression newGuidExpr = Expression.New(typeof(Guid).GetConstructor(new Type[] { typeof(string) }), getValueExpr); convertExpr = Expression.Convert(newGuidExpr, propertyType);
}
else if (genericType != fieldType)
{
convertExpr = Expression.Call(typeof(Convert).GetMethod(methodName, new Type[] { fieldType }), getValueExpr);
convertExpr = Expression.Convert(convertExpr, propertyType);
}
else
{
convertExpr = Expression.Convert(getValueExpr, propertyType);
}
}
else
{
if (propertyType == typeof(Guid))
{
Expression newGuidExpr = Expression.New(typeof(Guid).GetConstructor(new Type[] { typeof(string) }), getValueExpr); convertExpr = newGuidExpr;
}
else if (methodName != null && methodReturnType != fieldType)
{
convertExpr = Expression.Call(typeof(Convert).GetMethod(methodName, new Type[] { fieldType }), getValueExpr); if (propertyType != methodReturnType)
{
convertExpr = Expression.Convert(convertExpr, propertyType);
}
}
else
{
if (propertyType != methodReturnType || propertyType == typeof(byte[]))
{
convertExpr = Expression.Convert(getValueExpr, propertyType);
}
else if (propertyType != methodReturnType || propertyType.BaseType == typeof(Array))
{
convertExpr = Expression.Convert(getValueExpr, propertyType);
}
else
{
convertExpr = getValueExpr;
}
}
}
}
else
{
convertExpr = getValueExpr;
} return convertExpr;
}
#endregion #region GetIDataRecordMethod 获取IDataRecord方法名称和返回值类型
/// <summary>
/// 获取IDataRecord方法名称和返回值类型
/// </summary>
private static string GetIDataRecordMethod(ref Type fieldType)
{
string methodName = "GetValue"; if (fieldType == typeof(string))
{
methodName = "GetString";
}
else if (fieldType == typeof(object))
{
methodName = "GetValue";
}
else if (fieldType == typeof(byte[]))
{
methodName = "GetValue";
fieldType = typeof(object);
}
else if (fieldType == typeof(Guid))
{
methodName = "GetString";
fieldType = typeof(string);
}
else if (fieldType == typeof(char))
{
methodName = "GetChar";
}
else if (fieldType == typeof(byte))
{
methodName = "GetByte";
}
else if (fieldType == typeof(sbyte))
{
methodName = "GetValue";
fieldType = typeof(object);
}
else if (fieldType == typeof(short))
{
methodName = "GetInt16";
}
else if (fieldType == typeof(ushort))
{
methodName = "GetValue";
fieldType = typeof(object);
}
else if (fieldType == typeof(int))
{
methodName = "GetInt32";
}
else if (fieldType == typeof(uint))
{
methodName = "GetValue";
fieldType = typeof(object);
}
else if (fieldType == typeof(long))
{
methodName = "GetInt64";
}
else if (fieldType == typeof(ulong))
{
methodName = "GetValue";
fieldType = typeof(object);
}
else if (fieldType == typeof(float))
{
methodName = "GetFloat";
}
else if (fieldType == typeof(double))
{
methodName = "GetDouble";
}
else if (fieldType == typeof(decimal))
{
methodName = "GetDecimal";
}
else if (fieldType == typeof(bool))
{
methodName = "GetBoolean";
}
else if (fieldType == typeof(DateTime))
{
methodName = "GetDateTime";
}
// ======== 以下是可空类型 ================================
else if (fieldType == typeof(Guid?))
{
methodName = "GetString";
fieldType = typeof(string);
}
else if (fieldType == typeof(char?))
{
methodName = "GetChar";
fieldType = typeof(char);
}
else if (fieldType == typeof(byte?))
{
methodName = "GetByte";
fieldType = typeof(byte);
}
else if (fieldType == typeof(sbyte?))
{
methodName = "GetValue";
fieldType = typeof(object);
}
else if (fieldType == typeof(short?))
{
methodName = "GetInt16";
fieldType = typeof(short);
}
else if (fieldType == typeof(ushort?))
{
methodName = "GetValue";
fieldType = typeof(object);
}
else if (fieldType == typeof(int?))
{
methodName = "GetInt32";
fieldType = typeof(int);
}
else if (fieldType == typeof(uint?))
{
methodName = "GetValue";
fieldType = typeof(object);
}
else if (fieldType == typeof(long?))
{
methodName = "GetInt64";
fieldType = typeof(long);
}
else if (fieldType == typeof(ulong?))
{
methodName = "GetValue";
fieldType = typeof(object);
}
else if (fieldType == typeof(float?))
{
methodName = "GetFloat";
fieldType = typeof(float);
}
else if (fieldType == typeof(double?))
{
methodName = "GetDouble";
fieldType = typeof(double);
}
else if (fieldType == typeof(decimal?))
{
methodName = "GetDecimal";
fieldType = typeof(decimal);
}
else if (fieldType == typeof(bool?))
{
methodName = "GetBoolean";
fieldType = typeof(bool);
}
else if (fieldType == typeof(DateTime?))
{
methodName = "GetDateTime";
fieldType = typeof(DateTime);
} return methodName;
}
#endregion #region GetConvertMethod 获取Convert类的方法名称和返回值类型
/// <summary>
/// 获取Convert类的方法名称和返回值类型
/// </summary>
private static string GetConvertMethod(Type propertyType, out Type methodReturnType)
{
string methodName = null;
methodReturnType = propertyType; if (propertyType == typeof(string))
{
methodName = "ToString";
}
else if (propertyType == typeof(char))
{
methodName = "ToChar";
}
else if (propertyType == typeof(byte))
{
methodName = "ToByte";
}
else if (propertyType == typeof(sbyte))
{
methodName = "ToByte";
methodReturnType = typeof(byte);
}
else if (propertyType == typeof(short))
{
methodName = "ToInt16";
}
else if (propertyType == typeof(ushort))
{
methodName = "ToInt16";
methodReturnType = typeof(short);
}
else if (propertyType == typeof(int))
{
methodName = "ToInt32";
}
else if (propertyType == typeof(uint))
{
methodName = "ToInt32";
methodReturnType = typeof(int);
}
else if (propertyType == typeof(long))
{
methodName = "ToInt64";
}
else if (propertyType == typeof(ulong))
{
methodName = "ToInt64";
methodReturnType = typeof(long);
}
else if (propertyType == typeof(float))
{
methodName = "ToSingle";
}
else if (propertyType == typeof(double))
{
methodName = "ToDouble";
}
else if (propertyType == typeof(decimal))
{
methodName = "ToDecimal";
}
else if (propertyType == typeof(bool))
{
methodName = "ToBoolean";
}
else if (propertyType == typeof(DateTime))
{
methodName = "ToDateTime";
}
// ======== 以下是可空类型 ================================
else if (propertyType == typeof(char?))
{
methodName = "ToChar";
}
else if (propertyType == typeof(byte?))
{
methodName = "ToByte";
}
else if (propertyType == typeof(sbyte?))
{
methodName = "ToByte";
methodReturnType = typeof(byte);
}
else if (propertyType == typeof(short?))
{
methodName = "ToInt16";
}
else if (propertyType == typeof(ushort?))
{
methodName = "ToInt16";
methodReturnType = typeof(short);
}
else if (propertyType == typeof(int?))
{
methodName = "ToInt32";
}
else if (propertyType == typeof(uint?))
{
methodName = "ToInt32";
methodReturnType = typeof(int);
}
else if (propertyType == typeof(long?))
{
methodName = "ToInt64";
}
else if (propertyType == typeof(ulong?))
{
methodName = "ToInt64";
methodReturnType = typeof(long);
}
else if (propertyType == typeof(float?))
{
methodName = "ToSingle";
}
else if (propertyType == typeof(double?))
{
methodName = "ToDouble";
}
else if (propertyType == typeof(decimal?))
{
methodName = "ToDecimal";
}
else if (propertyType == typeof(bool?))
{
methodName = "ToBoolean";
}
else if (propertyType == typeof(DateTime?))
{
methodName = "ToDateTime";
} return methodName;
}
#endregion }
}

如何使用

实体类列表赋值

private void DataReaderToList<T>(IDataReader rd, ref List<T> list) where T : new()
{
if (typeof(T) == typeof(int))
{
while (rd.Read())
{
list.Add((T)rd[0]);
}
}
else if (typeof(T) == typeof(string))
{
while (rd.Read())
{
list.Add((T)rd[0]);
}
}
else
{
PropertyInfoEx[] propertyInfoList = GetEntityProperties(typeof(T)); int fcnt = rd.FieldCount;
StringBuilder strFields = new StringBuilder();
Dictionary<string, int> fields = new Dictionary<string, int>();
Dictionary<string, Type> fieldTypes = new Dictionary<string, Type>();
for (int i = 0; i < fcnt; i++)
{
string field = rd.GetName(i).ToUpper();
if (!fields.ContainsKey(field))
{
fields.Add(field, i);
fieldTypes.Add(field, rd.GetFieldType(i));
strFields.Append("_" + field);
}
} var func = ExpressionMapper.BindData<T>(propertyInfoList, fields, fieldTypes, strFields.ToString()); while (rd.Read())
{
T obj = func(rd); list.Add(obj);
}
}
}

实体类赋值

private void DataReaderToEntity(Type type, IDataReader rd, ref object result, ref bool hasValue)
{
PropertyInfoEx[] propertyInfoList = GetEntityProperties(type); int fieldCount = rd.FieldCount;
StringBuilder strFields = new StringBuilder();
Dictionary<string, int> fields = new Dictionary<string, int>();
Dictionary<string, Type> fieldTypes = new Dictionary<string, Type>();
for (int i = 0; i < fieldCount; i++)
{
string field = rd.GetName(i).ToUpper();
if (!fields.ContainsKey(field))
{
fields.Add(field, i);
fieldTypes.Add(field, rd.GetFieldType(i));
strFields.Append("_" + field);
}
} var func = ExpressionMapper.BindData(type, propertyInfoList, fields, fieldTypes, strFields.ToString()); while (rd.Read())
{
hasValue = true; result = func(rd);
}
}

使用Expression代替反射读取IDataReader或IDataRecord给实体类赋值的更多相关文章

  1. 读取Excel文件存储在实体类中

    1.Maven文件 <!--读取Excel的架包--> <dependency> <groupId>org.apache.poi</groupId> & ...

  2. [转]C#反射,根据反射将数据库查询数据和实体类绑定,并未实体类赋值

    本文来自:http://www.cnblogs.com/mrchenzh/archive/2010/05/31/1747937.html /****************************** ...

  3. .net 通过反射实现两个相同结构实体类的转换

    public static T2 CopyToModel<T1, T2>(T1 source) { T2 model = default(T2); PropertyInfo[] pi = ...

  4. .Net Core NPOI读取Excel 并转为数据实体类

    创建应用程序 这里直接创建Console程序 引用NPOI的NuGet包 PM> Install-Package NPOI -Version 2.5.1 直接Nuget包管理器添加 导入Exce ...

  5. 转 利用java反射实现两个具有相同属性bean赋值

    package com.dobn.bdgcgl.utils; import java.lang.reflect.Field; import java.lang.reflect.Method; publ ...

  6. Android利用反射机制为实体类属性赋值

    在做android项目时,有时会遇到从网络上获取json类型数据,赋值给实体类,实体类属性少可以一个一个的赋值,如果实体类有很多属性,赋值可能就要耗很长的功夫了,幸好Java给我们提供了反射机制.下面 ...

  7. 运用Mono.Cecil 反射读取.NET程序集元数据

    CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...

  8. SqlHelper简单实现(通过Expression和反射)1.引言

    之前老大说要改变代码中充斥着各种Select的Sql语句字符串的情况,让我尝试着做一个简单的SqlHelper,要具有以下功能: 1.不要在业务代码中暴露DataTable或者DataSet类型: 2 ...

  9. Java通过反射读取泛型

    1.在这里有必要先提一句关于javabean,建议有一个构造器,而不是必须要写的,这是一个良好的习惯. 这样做肯定是有好处的,如果你的一个类写了带参的构造方法,而没有写空的构造方法,那么,如有有一个类 ...

  10. 利用c#反射实现实体类生成以及数据获取与赋值

    转:http://hi.baidu.com/xyd21c/item/391da2fc8fb351c10dd1c8b8 原有的实体类成员逐个赋值与获取的方法弊端: 1.每次对实体类属性进行赋值时,都要检 ...

随机推荐

  1. 生命游戏(4.2leetcode每日打卡)

    根据 百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机. 给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞.每个细胞都具有一个初始状 ...

  2. 微信小程序直播接入指南

    微信小程序直播接入指南 小程序直播组件接入指引 一.简介 小程序直播,是微信提供给小程序开发者的直播组件.通过调用该组件,商家可以在小程序中实现直播功能. 按下面的使用说明接入,在你的小程序中引入直播 ...

  3. 从一个 Demo 说起 Dubbo3

    简介 2017年的9月份,阿里宣布重启Dubbo的开发维护,并且后续又将Dubbo捐献给了Apache,经过多年的发展已经发布到3.X版本了,Dubbo重启维护之后是否有值得我们期待的功能呢,下面就来 ...

  4. springcloud+nacos项目启动后,登陆连接服务器时超时:Connection timed out no further information

    问题现象:项目启动后,登陆连接服务器时超时:Connection timed out no further information 192.168.42.190:4004 原因:我的配置有问题,在na ...

  5. 怎么理解 Bean、Controller、Service、Servicelmpl、Mapper

    主要是对java的各层级介绍.叫法可能不一样,但实现的逻辑都差不多,扔给我的代码中是四个层,分别是Bean层.Controller层.Service层.Servicelmpl层.Mapper层. Be ...

  6. spring报错-Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 63

    这个错误原因是因为JDK版本过高,改一下版本就行了 把里面的19改成8 这样就行了

  7. Head First Java学习:第十一章-异常处理

    第十一章 异常处理 1.方法可以抓住其他方法所抛出的异常:异常总是丢回给调用方 有风险.会抛出异常的程序代码: 负责声明异常:创建Exception对象并抛出 调用该方法的程序代码: 在try中调用程 ...

  8. Keepalived 高可用详解

    Keepalived 详解 1.Keepalived介绍 ​ Keepalived是一个基于VRRP协议来实现LVS服务高可用方案,可以利用其来避免单点故障.一个LVS服务会使用2台服务器运行Keep ...

  9. BeanCurrentlyInCreationException解决当前容器创建异常、循环依赖问题

    BeanCurrentlyInCreationException解决当前容器创建异常.循环依赖问题 一.什么是循环依赖呢? 类A依赖类B,类B也依赖类A,这种情况就会出现循环依赖. Bean A → ...

  10. Python——CSS(层叠样式表,Cascading Style Sheets)、选择器(Selectors)

    CSS(层叠样式表,Cascading Style Sheets)是一种用于描述文档样式和布局的样式表语言.它可以与HTML结合使用,用于控制网页的外观和格式.以下是CSS的主要特点和一些基本概念: ...