突然想起来几年前我写的一个小东西,放上来大家评论一下,有兴趣的可以测试一下性能,呵呵。

原理很简单,利用 Lambda 表达式树生成一个 Delegate ,然后缓存起来。不多说了,下面上代码:

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Lenic.Extensions;
 
namespace Lenic.Data.Extensions
{
/// <summary>
/// IDataReader 扩展方法集合
/// </summary>
[DebuggerStepThrough]
public static class DataReaderExtensions
{
#region Private Methods
private static readonly Dictionary<Type, Delegate> cache = new Dictionary<Type, Delegate>();
private static readonly object cacheLocker = new object();
#endregion
 
#region Business Methods
/// <summary>
/// 返回指定字段的值, 并执行 ConvertTo 函数转换。
/// </summary>
/// <typeparam name="T">返回值类型。</typeparam>
/// <param name="reader">一个实现了 IDataReader 接口的实例对象。</param>
/// <param name="name">要查找的字段的名称。</param>
/// <returns>转换完毕的 T 类型的结果。</returns>
public static T Field<T>(this IDataReader reader, string name)
{
return reader[name].ConvertTo<T>(default(T), false);
}
 
/// <summary>
/// 返回指定字段的值, 并执行 ConvertTo 函数转换。
/// </summary>
/// <typeparam name="T">返回值类型。</typeparam>
/// <param name="reader">一个实现了 IDataReader 接口的实例对象。</param>
/// <param name="index">要查找的字段的索引。</param>
/// <returns>转换完毕的 T 类型的结果。</returns>
public static T Field<T>(this IDataReader reader, int index)
{
return reader[index].ConvertTo<T>(default(T), false);
}
 
/// <summary>
/// 解析当前 IDataReader 类型的实例对象并提取一个 T 类型的列表。
/// </summary>
/// <typeparam name="T">待解析的元素类型, 该类型必须包含一个默认的构造函数。</typeparam>
/// <param name="reader">一个实现了 IDataReader 接口的实例对象。</param>
/// <returns>一个 T 类型的列表。</returns>
public static List<T> ToList<T>(this IDataReader reader) where T : class, new()
{
return Fill<T>(reader, DynamicCreateEntity<T>()).ToList();
}
 
/// <summary>
/// 解析当前 IDataReader 类型的实例对象并提取一个 T 类型的列表。
/// </summary>
/// <typeparam name="T">待解析的元素类型, 该类型必须包含一个默认的构造函数。</typeparam>
/// <param name="reader">一个实现了 IDataReader 接口的实例对象。</param>
/// <param name="predicate">映射委托。</param>
/// <returns>一个 T 类型的列表。</returns>
public static List<T> ToList<T>(this IDataReader reader, Func<IDataReader, T> predicate)
where T : class, new()
{
return Fill<T>(reader, predicate).ToList();
}
#endregion
 
#region Private Methods
/// <summary>
/// 创建一个 构造函数 委托。
/// </summary>
/// <typeparam name="T">构造目标类型。</typeparam>
/// <returns>构造完毕的 Func 委托。</returns>
private static Func<IDataReader, T> DynamicCreateEntity<T>() where T : class, new()
{
var type = typeof(T);
if (cache.ContainsKey(type))
return (Func<IDataReader, T>)cache[type];
 
lock (cacheLocker)
{
if (cache.ContainsKey(type))
return (Func<IDataReader, T>)cache[type];
 
var result = DynamicCreateEntityLogic<T>();
cache.Add(type, result);
return result;
}
}
 
/// <summary>
/// 创建一个 构造函数 委托(逻辑实现)。
/// </summary>
/// <typeparam name="T">构造目标类型。</typeparam>
/// <returns>构造完毕的 Func 委托。</returns>
private static Func<IDataReader, T> DynamicCreateEntityLogic<T>() where T : class, new()
{
// Compiles a delegate of the form (IDataReader r) => new T { Prop1 = r.Field<Prop1Type>("Prop1"), ... }
ParameterExpression r = Expression.Parameter(typeof(IDataReader), "r");
 
// Get Properties of the property can read and write
var props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CanRead && p.CanWrite)
.ToArray();
 
// Create property bindings for all writable properties
List<MemberBinding> bindings = new List<MemberBinding>(props.Length);
 
// Get the binding method
var method = typeof(DataReaderExtensions).GetMethods()
.First(p => p.Name == "Field" &&
p.GetParameters().Length == 2 &&
p.GetParameters()[1].ParameterType == typeof(string));
 
foreach (PropertyInfo property in (typeof(T).GetProperties()))
{
// Create expression representing r.Field<property.PropertyType>(property.Name)
MethodCallExpression propertyValue = Expression.Call(
method.MakeGenericMethod(property.PropertyType),
r, Expression.Constant(property.Name));
 
// Assign the property value to property through a member binding
MemberBinding binding = Expression.Bind(property, propertyValue);
bindings.Add(binding);
}
// Create the initializer, which instantiates an instance of T and sets property values
 
// using the member bindings we just created
Expression initializer = Expression.MemberInit(Expression.New(typeof(T)), bindings);
 
// Create the lambda expression, which represents the complete delegate (r => initializer)
Expression<Func<IDataReader, T>> lambda = Expression.Lambda<Func<IDataReader, T>>(initializer, r);
 
return lambda.Compile();
}
 
/// <summary>
/// 从一个 IDataReader 的实例对象中提取一个 T 类型的列表。
/// </summary>
/// <typeparam name="T">结果列表中的元素类型, 该类型必须包含一个默认的构造函数。</typeparam>
/// <param name="reader">一个实现了 IDataReader 接口的实例对象。</param>
/// <returns>一个 T 类型的列表。</returns>
private static IEnumerable<T> Fill<T>(IDataReader reader, Func<IDataReader, T> predicate) where T : class, new()
{
while (reader.Read())
yield return predicate(reader);
}
#endregion
}
}

上面用到了一个全能转换方法,代码如下:

#region Type Convert Extensions
private static string typeIConvertibleFullName = typeof(IConvertible).FullName;
 
/// <summary>
/// 将当前实例对象类型转换为 T 类型.
/// </summary>
/// <typeparam name="T">目标类型.</typeparam>
/// <param name="obj">当前实例.</param>
/// <returns>转换完成的 T 类型的一个实例对象.</returns>
public static T ConvertTo<T>(this object obj)
{
return ConvertTo(obj, default(T));
}
 
/// <summary>
/// 将当前实例对象类型转换为 T 类型.
/// </summary>
/// <typeparam name="T">目标类型.</typeparam>
/// <param name="obj">当前实例.</param>
/// <param name="defaultValue">转换失败时的返回值.</param>
/// <returns>转换完成的 T 类型的一个实例对象.</returns>
public static T ConvertTo<T>(this object obj, T defaultValue)
{
if (obj != null)
{
if (obj is T)
return (T)obj;
 
var sourceType = obj.GetType();
var targetType = typeof(T);
 
if (targetType.IsEnum)
return (T)Enum.Parse(targetType, obj.ToString(), true);
 
if (sourceType.GetInterface(typeIConvertibleFullName) != null &&
targetType.GetInterface(typeIConvertibleFullName) != null)
return (T)Convert.ChangeType(obj, targetType);
 
var converter = TypeDescriptor.GetConverter(obj);
if (converter != null && converter.CanConvertTo(targetType))
return (T)converter.ConvertTo(obj, targetType);
 
converter = TypeDescriptor.GetConverter(targetType);
if (converter != null && converter.CanConvertFrom(sourceType))
return (T)converter.ConvertFrom(obj);
 
throw new ApplicationException("convert error.");
}
throw new ArgumentNullException("obj");
}
 
/// <summary>
/// 将当前实例对象类型转换为 T 类型.
/// </summary>
/// <typeparam name="T">目标类型.</typeparam>
/// <param name="obj">当前实例.</param>
/// <param name="defaultValue">转换失败时的返回值.</param>
/// <param name="ignoreException">如果设置为 <c>true</c> 表示忽略异常信息, 直接返回缺省值.</param>
/// <returns>转换完成的 T 类型的一个实例对象.</returns>
public static T ConvertTo<T>(this object obj, T defaultValue, bool ignoreException)
{
if (ignoreException)
{
try
{
return obj.ConvertTo<T>(defaultValue);
}
catch
{
return defaultValue;
}
}
return obj.ConvertTo<T>(defaultValue);
}
#endregion

再次欢迎大家品鉴。java 培训

转载于:https://www.cnblogs.com/nncc/archive/2012/08/30/2663832.html

突然想起来几年前我写的 !相关推荐

  1. 程序员心中都有一个“静静”,想起它就能踏实写代码了

    一代文豪托尔斯泰在其三大传世名著之一的<安娜·卡列尼娜>中开篇明义,幸福的家庭都是相同的,不幸的家庭则各有各的不幸,而在所有这些不幸的家庭中,基本   上总会有一个共同的第三者,名曰&qu ...

  2. 22年前雷军写的代码,你见过吗?

    作为小米科技的创始人.董事长和首席执行官,雷军的名字如雷贯耳.网上出现一篇"刘强东的代码水平如何"的文章,有网友在下面回复"代码只服雷军".雷军的代码水平真的很 ...

  3. 重新审阅一年前自己写的代码.

    这一周在维护自己一年前才进公司写的代码.经过领导,同事,同学审视提出了各种建议.零零散散,总结如下: 1 变量命名 我原先直接用 FTPUtil test = new FTPUtil(); 修改成ft ...

  4. Python 之父谈 Python

    在宣传海报上,Python 之父 Guido van Rossum 在 EuroPython 2015 会议的发言分为讲话稿和现场问答部分,但是他上台后将全程改为现场问答的形式.他在回答现场观众的问题 ...

  5. python语言中文社区-Python 之父谈 Python-Go语言中文社区

    在宣传海报上,Python 之父 Guido van Rossum 在 EuroPython 2015 会议的发言分为讲话稿和现场问答部分,但是他上台后将全程改为现场问答的形式.他在回答现场观众的问题 ...

  6. 中国python之父是谁-Python之父:谈Python

    Python之父:谈Python 在宣传海报上,Python 之父 Guido van Rossum 在 EuroPython 2015 会议的发言分为讲话稿和现场问答部分,但是他上台后将全程改为现场 ...

  7. 从一道面试题谈起,大厂到底看重程序员的什么能力?

    唐磊,他谦逊的自我介绍,是"在阿里云打工的清华学渣". 上周的一篇<字符串比较,居然暗藏玄机>,我最早是在唐磊<这10行比较字符串相等的代码给我整懵了>里看 ...

  8. 天黑的时候,我又想起那首歌

    開始懂了 孙燕资 我居然没有调头 最残忍那一刻 静静看你走 一点都不像我 原来人会变得温和 是透澈的懂了 爱情是流动的 不由人的 何必激动着要理由 相信你仅仅是怕伤害我 不是骗我 非常爱过谁会舍得 把 ...

  9. 多年前那些优秀的工程师,后来都去哪儿了?

    这是头哥侃码的第241篇原创 上周末,我读初中的儿子突然问我:"爸爸,你是不是从好买离职了?" 我听完,忙惊讶地问他是怎么知道的. 他朝我做了个鬼脸,然后指了指我的手机说:&quo ...

  10. C 语言这么厉害,它自身是用什么语言写的?

    作者 | 刘欣 本文经授权转载自码农翻身(ID:coderising) 这是来自我的星球的一个提问:"C语言本身用什么语言写的?" 换个角度来问,其实是:C语言在运行之前,得编译才 ...

最新文章

  1. 计算机网络华为模拟器,资源分享之计算机网络虚拟实践
  2. 9年前的大一,我们这样为女生过37女生节【祝节日快乐】
  3. Spring中神奇@aotuWrited
  4. 使用dropwizard(3)-加入DI-dagger2
  5. 系统动力学模型_蓝谷学术动态|典型海洋生态系统动力学模型构建、应用及发展入选2020年经典中国国际出版工程...
  6. linux 输入8个字母进行排序,Linux排序命令sort详解
  7. java破坏双亲委派_java的类加载机制-双亲委派,破坏双亲委派
  8. ios低版本、微信浏览器低版本 不能使用的js语法总结
  9. python爬取高德poi数据_python3爬虫-高德地图POI数据的爬取
  10. [lammps教程] lammps建立纳米管模型
  11. 编译原理第三版陈火旺第二章答案
  12. 部署mongDB数据库服务
  13. 保存网页内容为PDF,支持文本复制,链接跳转
  14. opencv光线补偿_教你了解摄像机的背光补偿
  15. RDP服务针对性攻击、钓鱼邮件攻击和勒索病毒家族Phobos研究
  16. 人工智能必备数学基础--精华笔记
  17. oracle改字体大小_sqlplus改字体
  18. ad域控查看ldap端口命令_工作笔记(一)LDAP和AD介绍以及使用LDAP操作AD域
  19. Centos下启动和关闭MySQL
  20. 新闻资讯小程序app

热门文章

  1. Python爬虫入门教程 42-100 爬取儿歌多多APP数据-手机APP爬虫部分
  2. Vue.js 5 @慕课网
  3. 软件测试综合笔试题目及参考答案
  4. Android更新主线程UI的两种方式handler与runOnUiThread()
  5. lintcode:1-10题
  6. 在win7命令行使用ssh通过秘钥登录linux
  7. 关于PostThreadMessage以及创建线程消息队列
  8. Pytorch模型构造方法
  9. ApiPost自动化测试基础之:接口参数依赖的情景处理...
  10. Mybatis学习之接口编程