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. Chrome扩展的核心:manifest 文件(中)

    大家好,我是 dom 哥.我正在写关于 Chrome 扩展开发的系列文章,感兴趣的可以 点个小星星 . 在上一篇中已经完成了 Chrome 扩展的雏形,本篇接着介绍 manifest 中的可选字段,完 ...

  2. ElasticSearch之cat master API

    命令样例如下: curl -X GET "https://localhost:9200/_cat/master?v=true&pretty" --cacert $ES_HO ...

  3. 从零玩转第三方登录之WeChat公众号登陆-cong-ling-wan-zhuan-di-san-fang-deng-lu-zhi-wechat-gong-zhong-hao-deng-lu

    title: 从零玩转第三方登录之WeChat公众号登陆 date: 2022-09-03 16:32:57.876 updated: 2022-09-03 16:32:57.876 url: htt ...

  4. 【ASP.NET Core】使用SignalR推送服务器日志

    一个多月前接手了一个产线机器人项目,上位机以读写寄存器的方式控制机器人,服务器就是用 ASP.NET Core 写的 Web API.由于前一位开发者写的代码质量问题,导致上位机需要16秒才能启动.经 ...

  5. 善用 vscode 的批量和模板技巧来提效

    vs code 其实有很多实用的技巧可以在日常工作中带来很大的提效,但可能是开发中没有相应的痛点场景,因此有些技巧接触的人不多 本篇就来介绍下多光标的批量操作和模板代码两种技巧在日常工作中的提效 涉及 ...

  6. MinIO FTP 断点续传

    MinIO FTP 断点续传 对于minio来说,使用minio官方的Java SDK和开启FTP都是不支持断点续传的.对于要实现http接口的断点续传,可以通过调用Amazon S3 REST AP ...

  7. 玩转Python:用Python处理文本数据,附代码

    Python 提供了多种库来处理纯文本数据,这些库可以应对从基本文本操作到复杂文本分析的各种需求.以下是一些常用的纯文本处理相关的库: str 类型: Python 内建的字符串类型提供了许多简便的方 ...

  8. Pikachu漏洞靶场 File Inclusion(文件包含漏洞)

    File Inclusion(文件包含漏洞) 本地文件包含 url: 192.168.171.30/pikachu/vul/fileinclude/fi_local.php?filename=file ...

  9. Harbor私有镜像仓库搭建

    为什么选择Harbor 你可能会问既然我们已经有了 Docker 镜像仓库为什么还需要 Harbor 呢?嗯,Harbor 是 Docker 镜像仓库的企业级扩展,用途更广泛.这些新的企业级功能包括: ...

  10. 在linux系统上怎么获取命令的帮助信息及man文档划分

    如何在linux系统上获取命令的帮助信息及man文档的章节划分 1.命令 -- help 2.man 命令 后者更加详细 首先帮助中尖括号<>和方括号[]以及省略号...的含义, 在方括号 ...