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. [ORB/BEBLID] 利用OpenCV(C++)实现尺度不变性与角度不变性的特征找图算法

    本文只发布于利用OpenCV实现尺度不变性与角度不变性的特征找图算法和知乎 一般来说,利用OpenCV实现找图功能,用的比较多的是模板匹配(matchTemplate).笔者比较喜欢里面的NCC算法. ...

  2. DES加密技术概述与应用

    一.引言 随着信息技术的飞速发展,数据安全已成为越来越受到重视的问题.数据加密技术作为保障信息安全的核心技术之一,得到了广泛的研究和应用.DES(Data Encryption Standard)作为 ...

  3. ABAP 泰国凭证批导 报错 F51 192 输入一个业务场景

    泰国凭证批导报错 F51 192 输入一个业务场景 方案一: 方案二:  ID_BUPLA  用户参数

  4. 基于DotNetty实现自动发布 - 实现一键打包发布

    前言 上一篇,我只实现了一键检测代码变化,本篇才是真正的实现了一键打包发布 效果图 客户端打包待发布文件 /// <summary> /// 把多个文件添加到压缩包 (保留文件夹层级关系) ...

  5. 从根上理解elasticsearch(lucene)查询原理(2)-lucene常见查询类型原理分析

    大家好,我是蓝胖子,在上一节我提到要想彻底搞懂elasticsearch 慢查询的原因,必须搞懂lucene的查询原理,所以在上一节我分析了lucene查询的整体流程,除此以外,还必须要搞懂各种查询类 ...

  6. K8s 里如何优雅地使用 /dev/shm 实现容器间共享内存

    目录 1. 从 docker run 的 --shm-size 参数聊起 2. Linux 里的 /dev/shm 3. Docker 对共享内存的支持 4. K8s 里如何设置 /dev/shm 大 ...

  7. flask统一异常捕获(作用:统一捕获指定的异常并返回)

    flask中可以使用装饰器errorhandler来对指定的异常.状态码等统一捕获并处理. 对指定的状态码进行统一捕获 @app.errorhandler(404) # 参数e是异常的详细信息的对象, ...

  8. hello Flask最简单的Flask项目

    # 1.导包 from flask import Flask # 2.实例化Flask对象.一般变量名都叫app,大家都是这样用,很多扩展插件的文档也是叫app,所以统一都叫app. # __name ...

  9. 【scikit-learn基础】--『监督学习』之 随机森林回归

    随机森林回归(Random Forest Regression)是一种在机器学习领域广泛应用的算法,由美国科学家 Leo Breiman 在2001年提出.它是一种集成学习方法,通过整合多个决策树的预 ...

  10. 解压.tar.gz文件的命令

    要解压以 .tar.gz 或 .tgz 扩展名结尾的文件,可以使用 tar 命令.通常,这些文件是使用 tar 和 gzip 压缩的.以下是解压 .tar.gz 文件的命令: tar -xzvf 文件 ...