private static Func <IDataRecord, o> getReaderConverter <o>(IDataRecord record) { Type typeIn = typeof(IDataRecord); Type typeOut = typeof(o); Delegate creator = null; if (!_expressionReaderCache.TryGetValue(typeOut, out creator)) { List <Expression> statements = new List <Expression>(); ParameterExpression peIn = Expression.Variable(typeIn); ParameterExpression peOut = Expression.Variable(typeOut); statements.Add(Expression.Assign(peOut, Expression.New(typeOut))); Type customAttrMapper = typeof(System.Data.Linq.Mapping.ColumnAttribute); BinaryExpression beAssignProp = null; System.Reflection.PropertyInfo[] props = typeOut.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); foreach (System.Reflection.PropertyInfo piOut in props) { int columnIndex = -1; try { //find column index System.Data.Linq.Mapping.ColumnAttribute[] attrs = (System.Data.Linq.Mapping.ColumnAttribute[])piOut.GetCustomAttributes(customAttrMapper, false); if (attrs.Length > 0) { columnIndex = record.GetOrdinal(attrs[0].Name); } else { columnIndex = record.GetOrdinal(piOut.Name); } } catch (IndexOutOfRangeException iorEx) { //skip if not match to any column continue; } ConstantExpression ce = Expression.Constant(columnIndex, typeof(int)); MethodCallExpression mce = null; MemberExpression meOut = Expression.Property(peOut, piOut.Name); if (piOut.PropertyType.IsGenericType) { mce = Expression.Call(peIn, typeIn.GetMethod("Get" + Nullable.GetUnderlyingType(piOut.PropertyType).Name), new Expression[] { ce }); beAssignProp = BinaryExpression.Assign(meOut, Expression.Convert(mce, piOut.PropertyType)); } else { mce = Expression.Call(peIn, typeIn.GetMethod("Get" + piOut.PropertyType.Name), new Expression[] { ce }); beAssignProp = BinaryExpression.Assign(meOut, mce); } MethodCallExpression mceCheck = Expression.Call(peIn, typeIn.GetMethod("IsDBNull"), new Expression[] { ce }); ConditionalExpression conde = Expression.IfThen(Expression.Not(mceCheck), beAssignProp); //statements.Add(beAssignProp); statements.Add(conde); } var returnStatement = peOut; statements.Add(returnStatement); var body = Expression.Block(new[] { peOut }, statements.ToArray()); var lamda = Expression.Lambda <Func <IDataRecord, o> >(body, peIn); creator = lamda.Compile(); _expressionReaderCache[typeOut] = creator; } return((Func <IDataRecord, o>)creator); }