从IDataReaderHelper中读取数据实体

2023-11-16

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

    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从IDataReaderHelper中读取数据实体 的相关文章

  • 从父类调用子类方法

    a doStuff 方法是否可以在不编辑 A 类的情况下打印 B did stuff 如果是这样 我该怎么做 class Program static void Main string args A a new A B b new B a
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • linux perf:如何解释和查找热点

    我尝试了linux perf https perf wiki kernel org index php Main Page今天很实用 但在解释其结果时遇到了困难 我习惯了 valgrind 的 callgrind 这当然是与基于采样的 pe
  • 当 contains() 工作正常时,xpath 函数ends-with() 工作时出现问题

    我正在尝试获取具有以特定 id 结尾的属性的标签 like span 我想获取 id 以 国家 地区 结尾的跨度我尝试以下xpath span ends with id Country 但我得到以下异常 需要命名空间管理器或 XsltCon
  • 如果使用 SingleOrDefault() 并在数字列表中搜索不在列表中的数字,如何返回 null?

    使用查询正数列表时SingleOrDefault 当在列表中找不到数字时 如何返回 null 或像 1 这样的自定义值 而不是类型的默认值 在本例中为 0 你可以使用 var first theIntegers Cast
  • 在数据库中搜索时忽略空文本框

    此代码能够搜索数据并将其加载到DataGridView基于搜索表单文本框中提供的值 如果我将任何文本框留空 则不会有搜索结果 因为 SQL 查询是用 AND 组合的 如何在搜索 从 SQL 查询或 C 代码 时忽略空文本框 private
  • 将自定义元数据添加到 jpeg 文件

    我正在开发一个图像处理项目 C 我需要在处理完成后将自定义元数据写入 jpeg 文件 我怎样才能做到这一点 有没有可用的图书馆可以做到这一点 如果您正在谈论 EXIF 元数据 您可能需要查看exiv2 http www exiv2 org
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • 如何将单个 char 转换为 int [重复]

    这个问题在这里已经有答案了 我有一串数字 例如 123456789 我需要提取它们中的每一个以在计算中使用它们 我当然可以通过索引访问每个字符 但是如何将其转换为 int 我研究过 atoi 但它需要一个字符串作为参数 因此 我必须将每个字
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • 插入记录后如何从SQL Server获取Identity值

    我在数据库中添加一条记录identity价值 我想在插入后获取身份值 我不想通过存储过程来做到这一点 这是我的代码 SQLString INSERT INTO myTable SQLString Cal1 Cal2 Cal3 Cal4 SQ
  • WCF:将随机数添加到 UsernameToken

    我正在尝试连接到用 Java 编写的 Web 服务 但有些东西我无法弄清楚 使用 WCF 和 customBinding 几乎一切似乎都很好 除了 SOAP 消息的一部分 因为它缺少 Nonce 和 Created 部分节点 显然我错过了一
  • C - 直接从键盘缓冲区读取

    这是C语言中的一个问题 如何直接读取键盘缓冲区中的数据 我想直接访问数据并将其存储在变量中 变量应该是什么数据类型 我需要它用于我们研究所目前正在开发的操作系统 它被称为 ICS OS 我不太清楚具体细节 它在 x86 32 位机器上运行
  • 有没有办法禁用 .NET 标签的“双击复制”功能?

    这真的很烦人 我使用标签作为列表项用户控件的一部分 用户可以单击它来选择列表项 然后双击它来重命名它 但是 如果剪贴板中有名称 双击标签会将其替换为标签文本 我还检查了应用程序中的其他标签 双击它们也会将其复制到剪贴板 我没有在这个程序中编
  • 32 位到 64 位内联汇编移植

    我有一段 C 代码 在 GNU Linux 环境下用 g 编译 它加载一个函数指针 它如何执行并不重要 使用一些内联汇编将一些参数推送到堆栈上 然后调用该函数 代码如下 unsigned long stack 1 23 33 43 save
  • ASP.NET MVC 6 (ASP.NET 5) 中的 Application_PreSendRequestHeaders 和 Application_BeginRequest

    如何在 ASP NET 5 MVC6 中使用这些方法 在 MVC5 中 我在 Global asax 中使用了它 现在呢 也许是入门班 protected void Application PreSendRequestHeaders obj
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐

  • flink中AggregateFunction 执行步骤以及含义全网详细解释

    package operator import org apache flink api common functions AggregateFunction import org apache flink api common funct
  • 我对 Kubernetes 的片面理解 —— 基础篇(持续更新中)

    Kubernetes 为何让我如此着迷 Kubernetes 的高矮胖瘦 介绍 Kubernetes 功能 Kubernetes 边界 声明式的配置 创建 Deployment 更新 Deployment 回滚 Deployment Kub
  • Python 3.9.0 已经可以下载了,但不支持win7和更低的系统版本!

    python3 9 0最近在官网可以下载了 而3 10 0a1已经开始测试了 根据python官网的说法 python3 9 0将不再支持win7或者win7以前的系统 下载来试了一下 win7果然不支持了 安装时报错 3 9的一些新功能
  • MongoDb随笔,PyMongo简单使用

    安装MongoDb 更新2021 07 06 https www mongodb com try download community 下载对应系统的软件版本 CentOS7 9 mongod 4 4 6 rpm ivh mongodb o
  • VSCode:Remote-SSH配置实录

    转自 VSCode Remote SSH配置实录 六天 CSDN博客 也可以通过这样一步步输入用户名和密码链接 为什么要使用VSCode Remote SSH 服务器很多时候都是部署在Linux远程机器上的 我们通常是SSH连过去然后用vi
  • JDBC——BasicDAO

    为什么要有 BasicDAO apache dbutils Druid 简化了 JDBC 开发 但还有不足 SQL语句是固定 不能通过参数传入 通用性不好 需要进行改进 更方便执行增删改查 对于 select 操作 如果有返回值 返回类型不
  • Putty配色方案(转)

    平时用Putty的频率相对挺高的 每次装完系统或是怎么的都得重新配色 还得百度去找配色表 每次太麻烦了 特地转载一篇好看的配色表供以后长期使用 以下内容为转载内容 使用的是修改注册表的方法 1 打开注册表 运行 regedit 2 找到对应
  • matlab仿真实例100题_输入-输出反馈线性化(Feedback linearization)控制算法Matlab仿真实例...

    反馈线性化 Feedback linearization 可能是大部分人接触非线性控制之后学习的第一种控制方法 个人认为主要优点有两点 一 它的理解和实现都相对简单 二 它能让非线性系统的转换为线性系统 这样接下来 就可以直接套用线性系统中
  • SQLEXPRESS服务无法启动

    一 软件版本 SQL Sever2014 localdb MSSQLLocalDB SQLServer13 0 VS2015 二 问题描述 由于使用web API中的odata编程 在工程中使用的是 localdb MSSQLLocalDB
  • Lintcode 464. 整数排序 II 冒泡排序三种实现 直接插入排序 直接选择排序 java

    一 冒泡排序 实现思路 https blog csdn net morewindows article details 6657829 Lintcode https www lintcode com problem sort integer
  • Ubuntu下安装及卸载JDK

    安装 1 添加 PPA repository 到系统 sudo add apt repository ppa webupd8team java 2 更新 sudo apt get update 3 下载安装 JDK sudo apt get
  • 算法专题之二叉树

    前言 树型数据结构广泛存在于现实世界中 比如家族族谱 企业职能架构等 它是一类在计算机领域被广泛应用的非线性数据结构 二叉树是树型数据中最常用的一类 本文从前端角度以js语法构建和操作二叉树的相关知识 基础概念 观察上图 二叉树的数据结构如
  • C++——大数加法

    大数加法 即运算的数据可能很大 int long long long无法存放 存在字符串中 但是加法的运算规则还是10进制 对于两个字符串 首先判断两者的长度 我们将字符串s设置为较长的字符串 方便后面的运算 也可以将t设置为较长的 从低位
  • 一文2000字详细介绍Android APP 常见概念与 adb 命令

    01 背景 因 team 正在推进 APP 自动化测试 那么主要业务是 IoT 相关的产品 既然是 APP 自动化测试 那么 Android APP 相关的一些概念与知识就很关键了 在之前遇到相关的问题都是现查现用 对于一些常用的概念和命令
  • 【Redis】常见数据结构及命令

    Redis常见命令 Redis数据结构介绍 Redis是一个key value的数据库 key一般是String类型 但是value的类型有很多种 Redis 通用命令 通用指令是部分数据类型的 都可以使用的指令 常见的有 KEYS 查看符
  • C++实现英语词典

    需要的东西 1 一个词典的txt文件 2 创建map容器 map
  • 最小二乘支持向量机”在学习偏微分方程 (PDE) 解方面的应用(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 本代码说明了 最小二乘支持向量机 在学习偏
  • 多媒体(视频容量计算)-软件设计(四十二)

    真题详解 有向图 软件设计 四十一 https blog csdn net ke1ying article details 129942490 一 音频概念 声音带宽 人耳 20Hz 20KHz 说话300 3400Hz 小于20Hz次声波
  • 上海链节科技:什么是企业链改?

    如何定义链改 链改 即用区块链中的部分技术原理和机制来改造业务系统中特定的部分 以创造更高效 更有公信力的系统 甚至还包括利用区块链上的各类积分 Token通证 来重新分配业务系统进而间接的改进业务系统背后的生产关系 传统基本结构的公司 通
  • 从IDataReaderHelper中读取数据实体

    using System using System Collections Generic using System Linq using System Text using System Data using System Reflect