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. (Good topic)哈希表:拼写单词 (3.17 leetcode每日打卡)

    给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars. 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌 ...

  2. C/C++字符函数库<ctype.h>/<cctype>(常用)

    头文件:<ctype.h> 形式:int 函数(int c)  参数:传入的一定是一个字符或者EOF 返回值:满足条件返回非0(true),否则返回0: int isalnum(int c ...

  3. 深入了解Rabbit加密技术:原理、实现与应用

    一.引言 在信息时代,数据安全愈发受到重视,加密技术作为保障信息安全的核心手段,得到了广泛的研究与应用.Rabbit加密技术作为一种新型加密方法,具有较高的安全性和便捷性.本文将对Rabbit加密技术 ...

  4. Guava Preconditions类的各种用法

    公众号「架构成长指南」,专注于生产实践.云原生.分布式系统.大数据技术分享. Guava Preconditions类 提供静态方法列表,用于检查是否使用有效参数值调用方法或构造函数.如果前提条件失败 ...

  5. python在使用过程中安装库的方法

    背景: 在学习python的过程中难免会出现python解释器中没有所需要的库,这时我们就要自行的去安装这些库了:当然如果使用的anaconda集成环境的话在安装python一些依赖环境中会简单不少( ...

  6. 后端程序员必会的前端知识-02:JavaScript

    第二章. Javascript 它是一种脚本语言,可以用来更改页面内容,控制多媒体,制作图像.动画等等 例子 修改页面内容 js 代码位置 <script> // js 代码 </s ...

  7. 聊一聊 C# 线程切换后上下文都去了哪里

    一:背景 1. 讲故事 总会有一些朋友是不是问一个问题,在 Windows 中线程做了上下文切换,请问被切的线程他的寄存器上下文都去了哪里?能不能给我挖出来?这个问题其实比较底层,如果对操作系统没有个 ...

  8. vue3在父子组件使用v-model双向绑定

    父组件: <script setup> import InputBox from "@/compon/InputBox.vue"; import {ref} from ...

  9. 小乌龟(TortoiseGit)配置SSH

    小乌龟(TortoiseGit)配置SSH 使用gerrit作为项目管理,使用console窗口命令,我真是不记得太多git命令,因此交给小乌龟可视化操作,简单方便.这里记录下配置SSH公钥私钥. 前 ...

  10. 2024年,在风云际会的编程世界里,窥探Java的前世今生,都说它穷途末路,我认为是柳暗花明!

    2024年,在风云际会的编程世界里,窥探Java的前世今生,都说它穷途末路,我认为是柳暗花明! 文编|JavaBuild 哈喽,大家好呀!我是JavaBuild,以后可以喊我鸟哥,嘿嘿!俺滴座右铭是不 ...