private static MethodInfo GetSqlMapperQueryMethod(MappingFunctionDescriptor funcDescriptor) { MethodInfo firstOrDefault = typeof(SqlMapper).GetMethods() .FirstOrDefault( m => m.Name == "Query" && m.IsGenericMethod && m.GetGenericArguments().Length == funcDescriptor.GenericTypes.Length); if (firstOrDefault != null) { return(firstOrDefault.MakeGenericMethod(funcDescriptor.GenericTypes)); } return(null); }
BuildFunction <TReturn, TFunc>() { var mappingDescriptor = new MappingFunctionDescriptor(typeof(TFunc)); MethodInfo queryMethodSignature = GetSqlMapperQueryMethod(mappingDescriptor); // variables that are visible in main scope var variables = new List <ParameterExpression>(); //body of main query method var methodBodyExpressions = new List <Expression>(); ////query method incoming parameters //var queryMethodParameters = new List<ParameterExpression>(); // parameters for fake map function var mappingParameters = new List <ParameterExpression>(); // body for fake map function var mappingBodyExpressions = new List <Expression>(); // declare and assign dictionaries and id evaluators for mapped types foreach (Type type in mappingDescriptor.GenericTypes.Take(mappingDescriptor.GenericTypes.Length - 1)) { IStructureMap mapper = LeanMapper.GetMapper(type); mappingParameters.Add(Expression.Parameter(type)); if (mapper == null) { continue; } SetupIdDataChecker(variables, methodBodyExpressions, mappingParameters.Last(), mappingBodyExpressions, mapper); } // declare parameters for main query method (they will be passed down to inner SqlMapper.Query method call) ParameterExpression cnnP = Expression.Parameter(typeof(IDbConnection), "cnn"); ParameterExpression sqlP = Expression.Parameter(typeof(string), "sql"); ParameterExpression mapParam = Expression.Parameter(mappingDescriptor.MappingType, "map"); ParameterExpression paramP = Expression.Parameter(typeof(object), "param"); ParameterExpression transactionP = Expression.Parameter(typeof(IDbTransaction), "transaction"); ParameterExpression bufferedP = Expression.Parameter(typeof(bool), "buffered"); ParameterExpression splitOnP = Expression.Parameter(typeof(string), "splitOn"); ParameterExpression commandTimeoutP = Expression.Parameter(typeof(int?), "commandTimeout"); ParameterExpression commandTypeP = Expression.Parameter(typeof(CommandType?), "commandType"); ParameterExpression newMapper = Expression.Parameter(mappingDescriptor.MappingType, "newMapper"); methodBodyExpressions.Add(Expression.Assign(newMapper, FinishFakeMappingFunction <TReturn, TFunc>(mapParam, mappingParameters, mappingBodyExpressions))); variables.Add(newMapper); //call REAL Query Method MethodCallExpression callRealDapperMethod = Expression.Call(queryMethodSignature, cnnP, sqlP, newMapper, paramP, transactionP, bufferedP, splitOnP, commandTimeoutP, commandTypeP); LabelTarget returnFinalTarget = Expression.Label(typeof(IEnumerable <TReturn>)); GotoExpression returnFinalValue = Expression.Return(returnFinalTarget, callRealDapperMethod); LabelExpression rerturnFinalExpression = Expression.Label(returnFinalTarget, Expression.Default(typeof(IEnumerable <TReturn>))); methodBodyExpressions.Add(returnFinalValue); methodBodyExpressions.Add(rerturnFinalExpression); return (Expression .Lambda <Func <IDbConnection, string, TFunc, dynamic, IDbTransaction, bool, string, int?, CommandType?, IEnumerable <TReturn> > >( Expression.Block(variables, methodBodyExpressions), cnnP, sqlP, mapParam, paramP, transactionP, bufferedP, splitOnP, commandTimeoutP, commandTypeP).Compile()); }