从IDataReaderHelper中读取数据实体

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
using System.Linq.Expressions;
using System.Threading;


public static class IDataReaderHelper
   {

       #region 核心代码

       /// <summary>
       /// 将IDataReader 转换为指定的类型,动态预编译,调用时注意不要重复调用
       /// 性能上要优于反射,对于10*500*10000条数据的反序列化,
       /// lambda 表达式 的性能是 反射的 10倍左右(10*500平均值)
       /// </summary>
       /// <typeparam name="T"></typeparam>
       /// <param name="reader"></param>
       /// <returns></returns>
       public static Func<IDataReader, T> GetDeserializer<T>(IDataReader reader)
       {
           ParameterExpression paramReader = Expression.Parameter(typeof(IDataReader), "reader");
           //在内部构建 DbFieldReader 对象
           var dbReaderExpr = Expression.New(typeof(DbFieldReader).GetConstructor(new Type[] { typeof(IDataReader) }), new Expression[] { paramReader });

           Expression CreateDbFieldReader = Expression.Lambda<Func<IDataReader, DbFieldReader>>(dbReaderExpr, paramReader);

           ParameterExpression paramInner = Expression.Parameter(typeof(FieldReader), "dbreader");

           MethodInfo IsDBNull = typeof(FieldReader).GetMethod("IsDBNull", BindingFlags.Public | BindingFlags.Instance);

           var columnList = Enumerable.Range(0, reader.FieldCount).Select(index =>
           {
               Type NonNullTpype = TypeHelper.GetNonNullableType(reader.GetFieldType(index));
               return new
               {
                   Name = reader.GetName(index),
                   Index = index,
                   Type = NonNullTpype,
                   Reader = Expression.Condition(Expression.Call(paramInner, IsDBNull, Expression.Constant(index)),
                           Expression.Convert(Expression.Constant(TypeHelper.GetDefault(NonNullTpype)), NonNullTpype),
                           Expression.Call(paramInner, FieldReader.GetReaderMethod(NonNullTpype), new[] { Expression.Constant(index) }))
               };
           });


           ConstructorInfo[] constructor = typeof(T).GetConstructors();
           Expression lambdaBody;
           IEnumerable<ColumnInfo> bindList = typeof(T).GetProperties().Select(obj =>
           {
               Type NonNullType = TypeHelper.GetNonNullableType(obj.PropertyType);

               var columnInfo = columnList.FirstOrDefault(col => col.Type == NonNullType && string.Equals(col.Name, obj.Name, StringComparison.CurrentCultureIgnoreCase));
               MemberInfo member = obj as MemberInfo;
               if (columnInfo == null)
               {
                   return new ColumnInfo { Expression = Expression.Convert(Expression.Constant(TypeHelper.GetDefault(NonNullType)), obj.PropertyType), Info = member };
               }

               //binding 类型必须一致
               Expression expr;
               if (obj.PropertyType != NonNullType)
               {
                   expr = Expression.Convert(columnInfo.Reader, obj.PropertyType);
               }
               else
               {
                   expr = columnInfo.Reader;
               }
               return new ColumnInfo
               {
                   Expression = expr,
                   Info = member
               };
           });

           if (constructor.Any(ctor => ctor.GetParameters().Length == 0))
           {
               lambdaBody = Expression.MemberInit(Expression.New(typeof(T)), bindList.Select(obj => Expression.Bind(obj.Info, obj.Expression) as MemberBinding));
           }
           else
           {
               ConstructorInfo ctor = constructor.FirstOrDefault(obj => obj.GetParameters().Length == bindList.Count());
               if (ctor == null) throw new ArgumentException(" 不可实例化该对象 ");
               lambdaBody = Expression.New(ctor, bindList.Select(obj => obj.Expression).ToArray());
           }
           LambdaExpression subLambda = Expression.Lambda<Func<FieldReader, T>>(lambdaBody, paramInner);
           Expression invoke = Expression.Invoke(subLambda, Expression.Invoke(CreateDbFieldReader, paramReader));
           Func<IDataReader, T> projector = Expression.Lambda<Func<IDataReader, T>>(invoke, paramReader).Compile();
           return projector;
       }
       internal class ColumnInfo
       {
           public Expression Expression { get; set; }
           public MemberInfo Info { get; set; }
       }
       public abstract class FieldReader
       {
           TypeCode[] typeCodes;

           public FieldReader()
           {
           }

           protected void Init()
           {
               this.typeCodes = new TypeCode[this.FieldCount];
           }

           public abstract int FieldCount { get; }
           public abstract Type GetFieldType(int ordinal);
           public abstract bool IsDBNull(int ordinal);
           protected abstract T GetValue<T>(int ordinal);
           protected abstract Byte GetByte(int ordinal);
           protected abstract Char GetChar(int ordinal);
           protected abstract DateTime GetDateTime(int ordinal);
           protected abstract Decimal GetDecimal(int ordinal);
           protected abstract Double GetDouble(int ordinal);
           protected abstract Single GetSingle(int ordinal);
           protected abstract Guid GetGuid(int ordinal);
           protected abstract Int16 GetInt16(int ordinal);
           protected abstract Int32 GetInt32(int ordinal);
           protected abstract Int64 GetInt64(int ordinal);
           protected abstract String GetString(int ordinal);

           public T ReadValue<T>(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(T);
               }
               return this.GetValue<T>(ordinal);
           }

           public T? ReadNullableValue<T>(int ordinal) where T : struct
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(T?);
               }
               return this.GetValue<T>(ordinal);
           }

           public Byte ReadByte(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Byte);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Byte)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Byte)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Byte)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Byte)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Byte)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Byte)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Byte>(ordinal);
                   }
               }
           }

           public Byte? ReadNullableByte(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Byte?);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Byte)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Byte)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Byte)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Byte)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Byte)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Byte)this.GetDecimal(ordinal);
                       default:
                           return (Byte)this.GetValue<Byte>(ordinal);
                   }
               }
           }

           public Char ReadChar(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Char);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Char)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Char)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Char)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Char)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Char)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Char)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Char)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Char>(ordinal);
                   }
               }
           }

           public Char? ReadNullableChar(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Char?);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Char)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Char)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Char)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Char)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Char)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Char)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Char)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Char>(ordinal);
                   }
               }
           }

           public DateTime ReadDateTime(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(DateTime);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.DateTime:
                           return this.GetDateTime(ordinal);
                       default:
                           return this.GetValue<DateTime>(ordinal);
                   }
               }
           }

           public DateTime? ReadNullableDateTime(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(DateTime?);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.DateTime:
                           return this.GetDateTime(ordinal);
                       default:
                           return this.GetValue<DateTime>(ordinal);
                   }
               }
           }

           public Decimal ReadDecimal(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Decimal);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Decimal)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Decimal)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Decimal)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Decimal)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Decimal)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Decimal)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Decimal>(ordinal);
                   }
               }
           }

           public Decimal? ReadNullableDecimal(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Decimal?);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Decimal)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Decimal)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Decimal)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Decimal)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Decimal)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Decimal)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Decimal>(ordinal);
                   }
               }
           }

           public Double ReadDouble(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Double);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Double)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Double)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Double)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Double)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Double)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Double)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Double>(ordinal);
                   }
               }
           }

           public Double? ReadNullableDouble(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Double?);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Double)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Double)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Double)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Double)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Double)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Double)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Double>(ordinal);
                   }
               }
           }

           public Single ReadSingle(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Single);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Single)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Single)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Single)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Single)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Single)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Single)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Single>(ordinal);
                   }
               }
           }

           public Single? ReadNullableSingle(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Single?);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Single)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Single)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Single)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Single)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Single)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Single)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Single>(ordinal);
                   }
               }
           }

           public Guid ReadGuid(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Guid);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case tcGuid:
                           return this.GetGuid(ordinal);
                       default:
                           return this.GetValue<Guid>(ordinal);
                   }
               }
           }

           public Guid? ReadNullableGuid(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Guid?);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case tcGuid:
                           return this.GetGuid(ordinal);
                       default:
                           return this.GetValue<Guid>(ordinal);
                   }
               }
           }

           public Int16 ReadInt16(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Int16);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Int16)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Int16)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Int16)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Int16)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Int16)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Int16)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Int16)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Int16>(ordinal);
                   }
               }
           }

           public Int16? ReadNullableInt16(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Int16?);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Int16)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Int16)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Int16)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Int16)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Int16)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Int16)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Int16)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Int16>(ordinal);
                   }
               }
           }

           public Int32 ReadInt32(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Int32);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Int32)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Int32)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Int32)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Int32)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Int32)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Int32)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Int32)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Int32>(ordinal);
                   }
               }
           }

           public Int32? ReadNullableInt32(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Int32?);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Int32)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Int32)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Int32)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Int32)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Int32)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Int32)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Int32)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Int32>(ordinal);
                   }
               }
           }

           public Int64 ReadInt64(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Int64);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Int64)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Int64)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Int64)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Int64)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Int64)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Int64)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Int64)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Int64>(ordinal);
                   }
               }
           }

           public Int64? ReadNullableInt64(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Int64?);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return (Int64)this.GetByte(ordinal);
                       case TypeCode.Int16:
                           return (Int64)this.GetInt16(ordinal);
                       case TypeCode.Int32:
                           return (Int64)this.GetInt32(ordinal);
                       case TypeCode.Int64:
                           return (Int64)this.GetInt64(ordinal);
                       case TypeCode.Double:
                           return (Int64)this.GetDouble(ordinal);
                       case TypeCode.Single:
                           return (Int64)this.GetSingle(ordinal);
                       case TypeCode.Decimal:
                           return (Int64)this.GetDecimal(ordinal);
                       default:
                           return this.GetValue<Int64>(ordinal);
                   }
               }
           }

           public String ReadString(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(String);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = Type.GetTypeCode(this.GetFieldType(ordinal));
                           continue;
                       case TypeCode.Byte:
                           return this.GetByte(ordinal).ToString();
                       case TypeCode.Int16:
                           return this.GetInt16(ordinal).ToString();
                       case TypeCode.Int32:
                           return this.GetInt32(ordinal).ToString();
                       case TypeCode.Int64:
                           return this.GetInt64(ordinal).ToString();
                       case TypeCode.Double:
                           return this.GetDouble(ordinal).ToString();
                       case TypeCode.Single:
                           return this.GetSingle(ordinal).ToString();
                       case TypeCode.Decimal:
                           return this.GetDecimal(ordinal).ToString();
                       case TypeCode.DateTime:
                           return this.GetDateTime(ordinal).ToString();
                       case tcGuid:
                           return this.GetGuid(ordinal).ToString();
                       case TypeCode.String:
                           return this.GetString(ordinal);
                       default:
                           return this.GetValue<String>(ordinal);
                   }
               }
           }

           public Byte[] ReadByteArray(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Byte[]);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Byte:
                           return new Byte[] { this.GetByte(ordinal) };
                       default:
                           return this.GetValue<Byte[]>(ordinal);
                   }
               }
           }

           public Char[] ReadCharArray(int ordinal)
           {
               if (this.IsDBNull(ordinal))
               {
                   return default(Char[]);
               }
               while (true)
               {
                   switch (typeCodes[ordinal])
                   {
                       case TypeCode.Empty:
                           typeCodes[ordinal] = GetTypeCode(ordinal);
                           continue;
                       case TypeCode.Char:
                           return new Char[] { this.GetChar(ordinal) };
                       default:
                           return this.GetValue<Char[]>(ordinal);
                   }
               }
           }

           private const TypeCode tcGuid = (TypeCode)20;
           private const TypeCode tcByteArray = (TypeCode)21;
           private const TypeCode tcCharArray = (TypeCode)22;

           private TypeCode GetTypeCode(int ordinal)
           {
               Type type = this.GetFieldType(ordinal);
               TypeCode tc = Type.GetTypeCode(type);
               if (tc == TypeCode.Object)
               {
                   if (type == typeof(Guid))
                       tc = tcGuid;
                   else if (type == typeof(Byte[]))
                       tc = tcByteArray;
                   else if (type == typeof(Char[]))
                       tc = tcCharArray;
               }
               return tc;
           }

           protected static bool IsNullableType(Type type)
           {
               return TypeHelper.IsNullableType(type);
               //return type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
           }
           protected static Type GetNonNullableType(Type type)
           {
               return TypeHelper.GetNonNullableType(type);
               //if (IsNullableType(type))
               //{
               //    return type.GetGenericArguments()[0];
               //}
               //return type;
           }
           public static MethodInfo GetReaderMethod(Type type)
           {
               if (_readerMethods == null)
               {
                   var meths = typeof(FieldReader).GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => m.Name.StartsWith("Read")).ToList();
                   _readerMethods = meths.ToDictionary(m => m.ReturnType);
                   _miReadValue = meths.Single(m => m.Name == "ReadValue");
                   _miReadNullableValue = meths.Single(m => m.Name == "ReadNullableValue");
               }

               MethodInfo mi;
               _readerMethods.TryGetValue(type, out mi);
               if (mi == null)
               {
                   if (IsNullableType(type))
                   {
                       mi = _miReadNullableValue.MakeGenericMethod(GetNonNullableType(type));
                   }
                   else
                   {
                       //如果没有该类型的方法,生成泛型方法
                       mi = _miReadValue.MakeGenericMethod(type);
                   }
               }
               return mi;
           }

           static Dictionary<Type, MethodInfo> _readerMethods;
           static MethodInfo _miReadValue;
           static MethodInfo _miReadNullableValue;
       }
       public class DbFieldReader : FieldReader
       {
           IDataReader reader;
           public DbFieldReader(IDataReader reader)
           {
               this.reader = reader;
               this.Init();
           }

           public override int FieldCount
           {
               get { return this.reader.FieldCount; }
           }

           public override Type GetFieldType(int ordinal)
           {
               return this.reader.GetFieldType(ordinal);
           }

           public override bool IsDBNull(int ordinal)
           {
               return this.reader.IsDBNull(ordinal);
           }

           protected override T GetValue<T>(int ordinal)
           {
               return (T)Convert(this.reader.GetValue(ordinal), typeof(T));
           }

           protected override Byte GetByte(int ordinal)
           {
               return this.reader.GetByte(ordinal);
           }

           protected override Char GetChar(int ordinal)
           {
               return this.reader.GetChar(ordinal);
           }

           protected override DateTime GetDateTime(int ordinal)
           {
               return this.reader.GetDateTime(ordinal);
           }

           protected override Decimal GetDecimal(int ordinal)
           {
               return this.reader.GetDecimal(ordinal);
           }

           protected override Double GetDouble(int ordinal)
           {
               return this.reader.GetDouble(ordinal);
           }

           protected override Single GetSingle(int ordinal)
           {
               return this.reader.GetFloat(ordinal);
           }

           protected override Guid GetGuid(int ordinal)
           {
               return this.reader.GetGuid(ordinal);
           }

           protected override Int16 GetInt16(int ordinal)
           {
               return this.reader.GetInt16(ordinal);
           }

           protected override Int32 GetInt32(int ordinal)
           {
               return this.reader.GetInt32(ordinal);
           }

           protected override Int64 GetInt64(int ordinal)
           {
               return this.reader.GetInt64(ordinal);
           }

           protected override String GetString(int ordinal)
           {
               return this.reader.GetString(ordinal);
           }
           private object GetDefault(Type type)
           {
               bool isNullable = !type.IsValueType || IsNullableType(type);
               if (!isNullable)
                   return Activator.CreateInstance(type);
               return null;
           }
           private object Convert(object value, Type type)
           {
               if (value == null)
               {
                   return GetDefault(type);
               }
               type = GetNonNullableType(type);
               Type vtype = value.GetType();
               if (type != vtype)
               {
                   if (type.IsEnum)
                   {
                       if (vtype == typeof(string))
                       {
                           return Enum.Parse(type, (string)value);
                       }
                       else
                       {
                           Type utype = Enum.GetUnderlyingType(type);
                           if (utype != vtype)
                           {
                               value = System.Convert.ChangeType(value, utype);
                           }
                           return Enum.ToObject(type, value);
                       }
                   }
                   return System.Convert.ChangeType(value, type);
               }
               return value;
           }
       }
       internal static class TypeHelper
       {
           public static bool IsNullableType(Type type)
           {
               return type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
           }
           public static Type GetNonNullableType(Type type)
           {
               if (IsNullableType(type))
               {
                   return type.GetGenericArguments()[0];
               }
               return type;
           }
           public static object GetDefault(Type type)
           {
               bool isNullable = !type.IsValueType || IsNullableType(type);
               if (!isNullable)
                   return Activator.CreateInstance(type);
               return null;
           }
       }

       #endregion

       #region 扩展方法部分

       /// <summary>
        /// DataSet 扩展方法,直接转换为指定的类
        /// 支持匿名对象,需动态调用
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ds"></param>
        /// <returns></returns>
        public static IEnumerable<T> ToEnumerable<T>(this DataSet ds)
        {
            if (ds == null || ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0) return new List<T>();
            using (IDataReader reader = ds.Tables[0].CreateDataReader())
            {
                return ReadData<T>(reader).ToList();
            }
        }
        /// <summary>
        /// dataset 转换为自定义的匿名类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ds"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        public static IEnumerable<T> ToAnonymousModel<T>(this DataSet ds, T model)
        {
            if (ds == null || ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0) return new List<T>();
            MethodInfo mi = typeof(IDataReaderHelper).GetMethod("ToEnumerable", BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(typeof(T));
            return mi.Invoke(null, new[] { ds }) as IEnumerable<T>;
        }
        private static IEnumerable<T> ReadData<T>(IDataReader reader)
        {
            try
            {
                var fn = IDataReaderHelper.GetDeserializer<T>(reader);
                while (reader.Read())
                {
                    yield return fn(reader);
                }
            }
            finally
            {
                reader.Dispose();
            }
        }

        #endregion

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值