/// <summary> /// Generate the method body for reading a IDataReader /// </summary> static Expression GenerateMethodBody(Expression reader, ValueMapping mapping) { var br = Expression.Label("break"); var itemType = (mapping is ValueMapping typed ? typed.Type : typeof(object)); var listType = typeof(List <>).MakeGenericType(itemType); var list = Expression.Variable(listType, "items"); var listInit = Expression.Assign(list, Expression.New(listType)); var loopCond = Expression.IfThen( Expression.Not(Expression.Call(reader, "Read", new Type[0])), Expression.Break(br) ); var loop = Expression.Loop( Expression.Block( loopCond, GenerateLoopBody(reader, list, mapping) ) , br); var body = Expression.Block( new ParameterExpression[] { list }, new Expression[] { listInit, loop, list } ); return(body); }
/// <summary> /// Generate an expression for a given mapping /// </summary> static Expression GenerateMapping(Expression reader, ValueMapping mapping) { switch (mapping) { case SingularMapping singular: return(GenerateSingularMapping(reader, singular)); case CtorMapping ctor: return(GenerateCtorMapping(reader, ctor)); case NullMapping _: throw new ArgumentException($"No mapping found between data reader columns and type '{mapping.Type}'"); default: throw new ArgumentException(); } }
/// <summary> /// Generate a method that takes a data reader and return a list of readed items /// </summary> /// <typeparam name="TReader">Specific reader type</typeparam> /// <typeparam name="TItem">Row type</typeparam> /// <param name="mapping">Constructor mapping</param> public static Expression <Func <TReader, List <TItem> > > GenerateReaderMethod <TReader, TItem>(ValueMapping mapping) { var readerType = typeof(TReader); if (readerType.IsInterface) { throw new ArgumentException("Pass an specific reader type"); } var readerArg = Expression.Parameter(readerType, "reader"); var body = GenerateMethodBody(readerArg, mapping); return(Expression.Lambda <Func <TReader, List <TItem> > >(body, readerArg)); }
public static Expression GenerateLoopBody(Expression reader, Expression list, ValueMapping mapping) { var itemType = (mapping is ValueMapping typed ? typed.Type : typeof(object)); var body = new List <Expression>(); var itemVar = Expression.Variable(itemType, "item"); body.Add(Expression.Assign(itemVar, GenerateMapping(reader, mapping))); body.Add(Expression.Call(list, "Add", new Type[0], itemVar)); var ret = Expression.Block( new[] { itemVar }, body.ToList() ); return(ret); }