private static Action <DbDataReader, T> GenerateAssignment <T>(INameResolver nameResolver, DbDataReader reader) where T : new() { var expressions = new List <Expression>(); var t = typeof(T); var targetParam = Expression.Parameter(t); var valueVariable = Expression.Variable(typeof(object)); var readerParam = Expression.Parameter(typeof(DbDataReader)); var getValueMethod = typeof(DbDataReader).GetTypeInfo().GetMethod("GetValue"); #if DEBUG var exceptionConstructor = typeof(InvalidCastException).GetConstructor(new [] { typeof(string), typeof(Exception) }); var exceptParam = Expression.Parameter(typeof(Exception)); #endif for (var i = 0; i < reader.VisibleFieldCount; i++) { var dbName = reader.GetName(i); var csharpName = nameResolver.DbToCSharp(dbName); expressions.Add(Expression.Assign(valueVariable, Expression.Call(readerParam, getValueMethod, Expression.Constant(i)))); Expression notNullBranch = null; if (csharpName == t.Name) { csharpName += "F"; } var field = t.GetTypeInfo().GetField(csharpName); if (field != null) { var fi = field.FieldType.GetTypeInfo(); foreach (var tcs in TypeConversionSpecializationsWithDefault) { if (tcs.Matches(fi, field.FieldType)) { #if DEBUG notNullBranch = Expression.TryCatch( Expression.Assign( Expression.Field(targetParam, field), tcs.Convert(fi, field.FieldType, valueVariable) ), Expression.Catch(exceptParam, Expression.Throw(Expression.New(exceptionConstructor, Expression.Constant(field.Name), exceptParam), field.FieldType)) ); #else notNullBranch = Expression.Assign( Expression.Field(targetParam, field), tcs.Convert(fi, field.FieldType, valueVariable) ); #endif break; } } } else { var property = t.GetTypeInfo().GetProperty(csharpName); if (property == null) { throw new ArgumentException($"field or property {csharpName} on type {t} not found for database column {dbName}"); } var ti = property.PropertyType.GetTypeInfo(); foreach (var tcs in TypeConversionSpecializationsWithDefault) { if (tcs.Matches(ti, property.PropertyType)) { #if DEBUG notNullBranch = Expression.TryCatch( Expression.Assign( Expression.Property(targetParam, property), tcs.Convert(ti, property.PropertyType, valueVariable) ), Expression.Catch(exceptParam, Expression.Throw(Expression.New(exceptionConstructor, Expression.Constant(property.Name), exceptParam), property.PropertyType)) ); #else notNullBranch = Expression.Assign( Expression.Property(targetParam, property), tcs.Convert(ti, property.PropertyType, valueVariable) ); #endif break; } } } var dbNullTest = Expression.Equal(valueVariable, Expression.Constant(DBNull.Value)); expressions.Add(Expression.IfThen(Expression.IsFalse(dbNullTest), notNullBranch)); } var block = Expression.Block( new[] { valueVariable }, expressions.ToArray() ); var action = Expression.Lambda <Action <DbDataReader, T> >(block, readerParam, targetParam).Compile(); return(action); }