Skip to content

Instantly share code, notes, and snippets.

@joshgo
Created March 19, 2013 13:16
Show Gist options
  • Save joshgo/5196023 to your computer and use it in GitHub Desktop.
Save joshgo/5196023 to your computer and use it in GitHub Desktop.
Simple reader extensions. Converts reader records into Entities/Objects - Support for simple types - And just dabbling with Expression Trees
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace ReaderExtensions.Extensions
{
public static class DataReaderExtensions
{
private static readonly Dictionary<Type, Delegate> _initializers = new Dictionary<Type, Delegate>();
public static T GetRow<T>(this System.Data.IDataReader reader)
{
var type = typeof(T);
if(!_initializers.ContainsKey(type))
_initializers.Add(type, GetInitializers<T>(reader));
return ((Func<System.Data.IDataReader, T>)_initializers[type])(reader);
}
private static Func<System.Data.IDataReader, T> GetInitializers<T>(System.Data.IDataReader reader)
{
var t_type = typeof(T);
var t_IDataRecord = typeof(System.Data.IDataRecord);
var t_this = typeof(DataReaderExtensions);
ParameterExpression readerParam = Expression.Parameter(typeof(System.Data.IDataReader), "reader");
List<MemberBinding> bindings = new List<MemberBinding>();
Dictionary<string, int> indexes = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
Dictionary<Type, string> readerMethods = new Dictionary<Type, string>();
Dictionary<Type, string> nullableMethods = new Dictionary<Type, string>();
for (int i = 0; i < reader.FieldCount; i++)
indexes.Add(reader.GetName(i), i);
readerMethods.Add(typeof(bool), "GetBoolean");
readerMethods.Add(typeof(byte), "GetByte");
readerMethods.Add(typeof(char), "GetChar");
readerMethods.Add(typeof(DateTime), "GetDateTime");
readerMethods.Add(typeof(decimal), "GetDecimal");
readerMethods.Add(typeof(double), "GetDouble");
readerMethods.Add(typeof(float), "GetFloat");
readerMethods.Add(typeof(Guid), "GetGuid");
readerMethods.Add(typeof(Int32), "GetInt32");
readerMethods.Add(typeof(Int16), "GetInt16");
readerMethods.Add(typeof(Int64), "GetInt64");
readerMethods.Add(typeof(object), "GetValue");
readerMethods.Add(typeof(string), "GetString");
nullableMethods.Add(typeof(Int16?), "GetNullableInt16");
nullableMethods.Add(typeof(Int32?), "GetNullableInt32");
nullableMethods.Add(typeof(Int64?), "GetNullableInt64");
foreach (var p in t_type.GetProperties())
{
Expression fieldExpression = null;
if (readerMethods.ContainsKey(p.PropertyType))
{
var method = t_IDataRecord.GetMethod(readerMethods[p.PropertyType], new[] { typeof(int) });
fieldExpression = Expression.Call(readerParam, method, Expression.Constant(indexes[p.Name], typeof(int)));
}
else if (nullableMethods.ContainsKey(p.PropertyType))
{
var method = t_this.GetMethod(nullableMethods[p.PropertyType], new[] { typeof(System.Data.IDataReader), typeof(int) });
fieldExpression = Expression.Call(method, readerParam, Expression.Constant(indexes[p.Name], typeof(int)));
}
bindings.Add(Expression.Bind(p, fieldExpression));
}
var memberInit = Expression.MemberInit(Expression.New(typeof(T)), bindings);
var initializationLambda = Expression.Lambda<Func<System.Data.IDataReader, T>>(memberInit, readerParam);
return initializationLambda.Compile();
}
private static Expression SetFieldFromMethod(Type type, string methodName, ParameterExpression readerParam, int index)
{
var method = type.GetMethod(methodName, new[] { typeof(System.Data.IDataReader), typeof(int) });
return Expression.Call(method, readerParam, Expression.Constant(index));
}
public static int? GetNullableInt16(this System.Data.IDataReader reader, int index)
{
Int16 val;
if (Int16.TryParse(reader.GetString(index), out val))
return val;
return null;
}
public static Int32? GetNullableInt32(this System.Data.IDataReader reader, int index)
{
Int32 val;
if (Int32.TryParse(reader.GetString(index), out val))
return val;
return null;
}
public static Int64? GetNullableInt64(this System.Data.IDataReader reader, int index)
{
Int64 val;
if (Int64.TryParse(reader.GetString(index), out val))
return val;
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment