【译】将IDataRecord自动填充到实体的扩展方法
Mapper:
/// <summary> /// 从提供的 DataRecord 对象创建新委托实例。 /// </summary> /// <param name="RecordInstance">表示一个 DataRecord 实例</param> /// <returns>从提供的 DataRecord 对象创建新委托实例。</returns> /// <remarks></remarks> private static Func<Record, Target> GetInstanceCreator(Record RecordInstance) {List<MemberBinding> Bindings = new List<MemberBinding>();Type TargetType = typeof(Target);Type SourceType = typeof(Record);ParameterExpression SourceInstance = Expression.Parameter(SourceType, "SourceInstance");MethodInfo GetSourcePropertyMethodExpression = SourceType.GetProperty("Item", new Type[] { typeof(int) }).GetGetMethod();DataTable SchemaTable = ((IDataReader)RecordInstance).GetSchemaTable();//通过在目标属性和字段在记录中的循环检查哪些是匹配的for (int i = 0; i <= RecordInstance.FieldCount - 1; i++){foreach (PropertyInfo TargetProperty in TargetType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) {//如果属性名和字段名称是一样的if (TargetProperty.Name.ToLower() == RecordInstance.GetName(i).ToLower() && TargetProperty.CanWrite) {//获取 RecordField 的类型Type RecordFieldType = RecordInstance.GetFieldType(i);//RecordField 可空类型检查if ((bool)(SchemaTable.Rows[i]["AllowDBNull"]) == true && RecordFieldType.IsValueType) {RecordFieldType = typeof(Nullable<>).MakeGenericType(RecordFieldType);}//为 RecordField 创建一个表达式Expression RecordFieldExpression = Expression.Call(SourceInstance, GetSourcePropertyMethodExpression, Expression.Constant(i, typeof(int)));//获取一个表示 SourceValue 的表达式Expression SourceValueExpression = GetSourceValueExpression(RecordFieldType, RecordFieldExpression);Type TargetPropertyType = TargetProperty.PropertyType;//从 RecordField 到 TargetProperty 类型的值转换Expression ConvertedRecordFieldExpression = GetConvertedRecordFieldExpression(RecordFieldType, SourceValueExpression, TargetPropertyType);MethodInfo TargetPropertySetter = TargetProperty.GetSetMethod();//为属性创建绑定var BindExpression = Expression.Bind(TargetPropertySetter, ConvertedRecordFieldExpression);//将绑定添加到绑定列表 Bindings.Add(BindExpression);}}}//创建 Target 的新实例并绑定到 DataRecordMemberInitExpression Body = Expression.MemberInit(Expression.New(TargetType), Bindings);return Expression.Lambda<Func<Record, Target>>(Body, SourceInstance).Compile(); }
现在我们需要从 IDataReader 创建一个 sourceproperty。
/// <summary> /// 获取表示 RecordField 真实值的表达式。 /// </summary> /// <param name="RecordFieldType">表示 RecordField 的类型。</param> /// <param name="RecordFieldExpression">表示 RecordField 的表达式。</param> /// <returns>表示 SourceValue 的表达式。</returns> private static Expression GetSourceValueExpression(Type RecordFieldType, Expression RecordFieldExpression) {//首先从 RecordField 取消装箱值,以便我们可以使用它UnaryExpression UnboxedRecordFieldExpression = Expression.Convert(RecordFieldExpression, RecordFieldType);//获取一个检查 SourceField 为 null 值的表达式UnaryExpression NullCheckExpression = Expression.IsFalse(Expression.TypeIs(RecordFieldExpression, typeof(DBNull)));ParameterExpression Value = Expression.Variable(RecordFieldType, "Value");//获取一个设置 TargetProperty 值的表达式Expression SourceValueExpression = Expression.Block(new ParameterExpression[] { Value }, Expression.IfThenElse(NullCheckExpression, Expression.Assign(Value, UnboxedRecordFieldExpression),Expression.Assign(Value, Expression.Constant(GetDefaultValue(RecordFieldType), RecordFieldType))), Expression.Convert(Value, RecordFieldType));return SourceValueExpression; }
现在把源转换到目标属性。
如果它们相同,只需要在装箱之前将源对象分配给目标属性。如果他们不同我们还需要将源对象强制转换为目标类型。
还有一个特殊情况,需要处理这里。没有操作符为原始类型转换为字符串。所以如果我们试试这个函数将抛出异常。这是通过调用 ToString 方法处理源。
/// <summary> /// Gets an expression representing the recordField converted to the TargetPropertyType /// </summary> /// <param name="RecordFieldType">The Type of the RecordField</param> /// <param name="UnboxedRecordFieldExpression">An Expression representing the Unboxed RecordField value</param> /// <param name="TargetPropertyType">The Type of the TargetProperty</param> /// <returns></returns> private static Expression GetConvertedRecordFieldExpression(Type RecordFieldType, Expression UnboxedRecordFieldExpression, Type TargetPropertyType) {Expression ConvertedRecordFieldExpression = default(Expression);if (object.ReferenceEquals(TargetPropertyType, RecordFieldType)){//Just assign the unboxed expressionConvertedRecordFieldExpression = UnboxedRecordFieldExpression;}else if (object.ReferenceEquals(TargetPropertyType, typeof(string))){//There are no casts from primitive types to String.//And Expression.Convert Method (Expression, Type, MethodInfo) only works with static methods.ConvertedRecordFieldExpression = Expression.Call(UnboxedRecordFieldExpression, RecordFieldType.GetMethod("ToString", Type.EmptyTypes));}else{//Using Expression.Convert works wherever you can make an explicit or implicit cast.//But it casts OR unboxes an object, therefore the double cast. First unbox to the SourceType and then cast to the TargetType//It also doesn't convert a numerical type to a String or date, this will throw an exception.ConvertedRecordFieldExpression = Expression.Convert(UnboxedRecordFieldExpression, TargetPropertyType);}return ConvertedRecordFieldExpression; }
为了使用其更快,我们将使用缓存
/// <summary> /// A Singleton construct that returns a precompiled delegate if it exists, otherwise it will create one /// </summary> /// <param name="RecordInstance"></param> /// <returns></returns> static internal Func<Record, Target> GetCreator(Record RecordInstance) {if (_Creator == null){lock (SyncRoot){if (_Creator == null){//Get Creator on first access_Creator = GetInstanceCreator(RecordInstance);}}}return _Creator; }
使用示例:
公有方法包括两个简单的扩展方法,所以 IDataRecord 所以使用映射器是很容易的。
/// <summary> /// ExtensionMethod that creates a List<Target> from the supplied IDataReader /// </summary> /// <param name="Reader"></param> /// <returns></returns> public static List<Target> ToList<Target>(this IDataReader Reader) where Target : class, new() {List<Target> List = new List<Target>();while (Reader.Read()){List.Add(CreateInstance<Target>(Reader));}return List; }/// <summary> /// ExtensionMethod that Creates an instance<Target>) from a DataRecord. /// </summary> /// <param name="Record">The DataRecord containing the values to set on new instance</param> /// <returns>An instance of Target class</returns> public static Target CreateInstance<Target>( this IDataRecord Record) where Target : class, new() {return (Mapper<IDataRecord, Target>.GetCreator(Record))(Record); }
可以像这样使用它:Reader.CreateInstance<MyClassInstance>
【译】将IDataRecord自动填充到实体的扩展方法相关推荐
- C#学习笔记四: C#3.0自动属性匿名属性及扩展方法
前言 这一章算是看这本书最大的收获了, Lambda表达式让人用着屡试不爽, C#3.0可谓颠覆了我们的代码编写风格. 因为Lambda所需篇幅挺大, 所以先总结C#3.0智能编译器给我们带来的诸多好 ...
- EXCEL,如果单元格会自动显示满格--被人设置了自动填充,改回来的方法
1 问题 如果你或者别人,不小心,让单元格变成了,自动显示满的效果,如下图,改怎么修改回来呢? 这种现实特点就是,如果单元格够长,是当前文本内容的长度整数倍,就显示为整数倍数,余数不管. 2 改回来的 ...
- Mybatis-plus的自动填充功能
1.概述 在我们开发过程中,经常需要做一些插入操作,有些麻烦,特别是对于一些每次插入或修改都需要改变的的一些字段,例如创建时间和修改时间两个字段,和数据没什么关系但是每次修改都需要被动修改这两个字段, ...
- php yanzhengm,ThinkPHP 在使用M方法(不创建模型类)时实现自动验证与自动填充
ThinkPHP M方法实现自动验证与自动填充 通常,我们会将自动验证与自动填充规则写入模型类里,然后再用 D 方法实例化模型类来实现对表单的自动验证与自动填充功能.由于 M 方法只是实例化基础模型类 ...
- ajax给表格填值,填报表用ajax实现关联单元格自动填充
在做填填报表用ajax实现关联单元格自动填充">报表.如果是简单的加减乘除运算,可以在单元格的自动计算里面实现:如果关联单元格显示的内容是从数据库中取出来的,就不能写加减乘除表达式来实 ...
- 360 html禁止自动填充,360浏览器的表单自动填充设置在哪?360浏览器自动填充表单的问题怎么解决?...
360浏览器的表单自动填充设置在哪?360浏览器自动填充表单的问题怎么解决? 很多用户都遇到了360浏览器自动填充表单的问题,那么怎么解决呢?今天带来360浏览器自动填充表单的问题解决方法分享. 开发 ...
- input密码输入框自动填充和提示
input密码输入框在前端会自动填充和提示的解决方法之一(谷歌浏览器) 1.原因 (个人猜测未证实)浏览器记住密码后,页面有密码输入框标签,浏览器会根据id和name属性从密码域中找到匹配的密码进行填 ...
- input修改自动填充背景色(单一色以及透明)
前言 最近想做一个比较好看的登录界面,就将输入框的背景色什么的都改了一遍,测试时基本效果都达到预期,唯独自动填充账号密码时,自己设置的输入框样式不起作用了,样式又变回默认的自动填充色了,这让我很苦恼- ...
- Android获取短信验证码并自动填充的两种方式
有些项目为了方便客户操作,减去客户输入短信验证码的时间,会要求安卓app能够获取收到的短信验证码并自动填充到输入框.所以,我整理了安卓获取短信验证码并自动填充输入框的两种方法,而且正式在项目中使用并无 ...
最新文章
- Tip #6 用ASP.NET AJAX判断当前浏览器类型
- Spring基于状态机squirrel-foundation简单使用
- 第五节 CImage和CBmp(二)
- python实现单例模式的三种方式及相关知识解释
- rootfs 制作ubuntu_Ubuntu12笔记: 基于busybox的Linux小系统制作
- kali系统apt设置代理
- 【JEECG技术博文】Local storage easyui extensions
- php 抓取 wordpress 文字内容,如何抓取WordPress文章
- 拿下微软、Google、Adobe,印度为何盛产科技圈 CEO?
- 第8章 数据库实例与操作模式
- 读取.properties配置文件(转载)
- 开启服务器防火墙 局域网内连接sqlserver数据库问题
- csv文件中文乱码转换
- httpd离线安装(含依赖包下载地址)
- ElasticSearch封装查询、多条件查询、模糊查询工具类
- 2020,中国互联网半坡起步
- 网上查询类网站!太恐怖了,什么都能查!!!!!(请注意最后)特实用!收藏吧!
- 编写函数求特殊a串和
- EBS功能_固定资产总结
- 概率统计之——方差分析