private StatementAttribute PreStatement(MethodInfo methodInfo, Type returnType, bool isTaskReturnType) { returnType = isTaskReturnType ? returnType.GetGenericArguments().FirstOrDefault() : returnType; var statementAttr = methodInfo.GetCustomAttribute <StatementAttribute>(); var methodName = methodInfo.Name; if (isTaskReturnType && methodInfo.Name.EndsWith("Async")) { methodName = methodName.Substring(0, methodName.Length - 5); } if (statementAttr != null) { statementAttr.Id = !String.IsNullOrEmpty(statementAttr.Id) ? statementAttr.Id : methodName; } else { statementAttr = new StatementAttribute { Id = methodName }; } if (returnType == typeof(DataTable)) { statementAttr.Execute = ExecuteBehavior.GetDataTable; return(statementAttr); } if (returnType == typeof(DataSet)) { statementAttr.Execute = ExecuteBehavior.GetDataSet; return(statementAttr); } if (statementAttr.Execute == ExecuteBehavior.Auto) { if (returnType == typeof(int) || returnType == _voidType || returnType == null) { statementAttr.Execute = ExecuteBehavior.Execute; } else if (returnType.IsValueType || returnType == typeof(string)) { statementAttr.Execute = ExecuteBehavior.ExecuteScalar; } else { var isQueryEnumerable = typeof(IEnumerable).IsAssignableFrom(returnType); if (isQueryEnumerable) { statementAttr.Execute = ExecuteBehavior.Query; } else { statementAttr.Execute = ExecuteBehavior.QuerySingle; } } } return(statementAttr); }
private static void EmitSetDataSourceChoice(ILGenerator ilGen, StatementAttribute statementAttr) { if (statementAttr.SourceChoice != DataSourceChoice.Unknow) { ilGen.LoadLocalVar(0); ilGen.LoadInt32(statementAttr.SourceChoice.GetHashCode()); ilGen.Callvirt(RequestContextType.Method.SetDataSourceChoice); } }
private static void EmitSetCommandType(ILGenerator ilGen, StatementAttribute statementAttr) { if (statementAttr.CommandType != CommandType.Text) { ilGen.LoadLocalVar(0); ilGen.LoadInt32(statementAttr.CommandType.GetHashCode()); ilGen.Callvirt(RequestContextType.Method.SetCommandType); } }
private static void SetCmdTypeAndSourceChoice(StatementAttribute statementAttr, ILGenerator ilGenerator) { if (statementAttr.CommandType != CommandType.Text) { ilGenerator.Emit(OpCodes.Ldloc_0); EmitUtils.LoadInt32(ilGenerator, statementAttr.CommandType.GetHashCode()); ilGenerator.Emit(OpCodes.Call, _set_CommandTypeMethod); } if (statementAttr.SourceChoice != DataSourceChoice.Unknow) { ilGenerator.Emit(OpCodes.Ldloc_0); EmitUtils.LoadInt32(ilGenerator, statementAttr.SourceChoice.GetHashCode()); ilGenerator.Emit(OpCodes.Call, _set_DataSourceChoiceMethod); } }
private MethodInfo PreExecuteMethod(StatementAttribute statementAttr, Type returnType, bool isTaskReturnType) { MethodInfo executeMethod; if (isTaskReturnType) { var realReturnType = returnType.GenericTypeArguments.FirstOrDefault(); switch (statementAttr.Execute) { case ExecuteBehavior.Execute: { executeMethod = typeof(ISmartSqlMapperAsync).GetMethod("ExecuteAsync", new Type[] { typeof(RequestContext) }); break; } case ExecuteBehavior.ExecuteScalar: { var method = typeof(ISmartSqlMapperAsync).GetMethod("ExecuteScalarAsync", new Type[] { typeof(RequestContext) }); executeMethod = method.MakeGenericMethod(realReturnType); break; } case ExecuteBehavior.QuerySingle: { var method = typeof(ISmartSqlMapperAsync).GetMethod("QuerySingleAsync", new Type[] { typeof(RequestContext) }); executeMethod = method.MakeGenericMethod(realReturnType); break; } case ExecuteBehavior.Query: { var method = typeof(ISmartSqlMapperAsync).GetMethod("QueryAsync", new Type[] { typeof(RequestContext) }); var enumerableType = realReturnType.GenericTypeArguments[0]; executeMethod = method.MakeGenericMethod(enumerableType); break; } case ExecuteBehavior.GetDataTable: { executeMethod = typeof(ISmartSqlMapperAsync).GetMethod("GetDataTableAsync", new Type[] { typeof(RequestContext) }); break; } case ExecuteBehavior.GetDataSet: { executeMethod = typeof(ISmartSqlMapperAsync).GetMethod("GetDataSetAsync", new Type[] { typeof(RequestContext) }); break; } case ExecuteBehavior.FillMultiple: { executeMethod = typeof(ISmartSqlMapperAsync).GetMethod("FillMultipleAsync", new Type[] { typeof(RequestContext), typeof(IMultipleResult) }); break; } case ExecuteBehavior.GetNested: { var method = typeof(ISmartSqlMapperAsync).GetMethod("GetNestedAsync", new Type[] { typeof(RequestContext) }); executeMethod = method.MakeGenericMethod(realReturnType); break; } default: { throw new ArgumentException(); } } } else { switch (statementAttr.Execute) { case ExecuteBehavior.Execute: { executeMethod = typeof(ISmartSqlMapper).GetMethod("Execute", new Type[] { typeof(RequestContext) }); break; } case ExecuteBehavior.ExecuteScalar: { var method = typeof(ISmartSqlMapper).GetMethod("ExecuteScalar", new Type[] { typeof(RequestContext) }); executeMethod = method.MakeGenericMethod(returnType); break; } case ExecuteBehavior.QuerySingle: { var method = typeof(ISmartSqlMapper).GetMethod("QuerySingle", new Type[] { typeof(RequestContext) }); executeMethod = method.MakeGenericMethod(returnType); break; } case ExecuteBehavior.Query: { var method = typeof(ISmartSqlMapper).GetMethod("Query", new Type[] { typeof(RequestContext) }); var enumerableType = returnType.GenericTypeArguments[0]; executeMethod = method.MakeGenericMethod(new Type[] { enumerableType }); break; } case ExecuteBehavior.GetDataTable: { executeMethod = typeof(ISmartSqlMapper).GetMethod("GetDataTable", new Type[] { typeof(RequestContext) }); break; } case ExecuteBehavior.GetDataSet: { executeMethod = typeof(ISmartSqlMapper).GetMethod("GetDataSet", new Type[] { typeof(RequestContext) }); break; } case ExecuteBehavior.FillMultiple: { executeMethod = typeof(ISmartSqlMapper).GetMethod("FillMultiple", new Type[] { typeof(RequestContext), typeof(IMultipleResult) }); break; } case ExecuteBehavior.GetNested: { var method = typeof(ISmartSqlMapper).GetMethod("GetNested", new Type[] { typeof(RequestContext) }); executeMethod = method.MakeGenericMethod(returnType); break; } default: { throw new ArgumentException(); } } } return(executeMethod); }
private StatementAttribute PreStatement(Type interfaceType, string scope, MethodInfo methodInfo, Type returnType, bool isTaskReturnType, ISmartSqlMapper smartSqlMapper) { returnType = isTaskReturnType ? returnType.GetGenericArguments().FirstOrDefault() : returnType; var statementAttr = methodInfo.GetCustomAttribute <StatementAttribute>(); var methodName = _sqlIdNamingConvert == null ? methodInfo.Name : _sqlIdNamingConvert.Invoke(interfaceType, methodInfo); if (isTaskReturnType && methodInfo.Name.EndsWith("Async") && _sqlIdNamingConvert == null) { methodName = methodName.Substring(0, methodName.Length - 5); } if (statementAttr != null) { statementAttr.Id = !String.IsNullOrEmpty(statementAttr.Id) ? statementAttr.Id : methodName; statementAttr.Scope = !String.IsNullOrEmpty(statementAttr.Scope) ? statementAttr.Scope : scope; } else { statementAttr = new StatementAttribute { Scope = scope, Id = methodName }; } if (returnType == typeof(DataTable)) { statementAttr.Execute = ExecuteBehavior.GetDataTable; return(statementAttr); } if (returnType == typeof(DataSet)) { statementAttr.Execute = ExecuteBehavior.GetDataSet; return(statementAttr); } if (IsValueTuple(returnType)) { statementAttr.Execute = ExecuteBehavior.FillMultiple; return(statementAttr); } if (statementAttr.Execute == ExecuteBehavior.Auto) { SqlCommandType cmdType = SqlCommandType.Unknown; if (String.IsNullOrEmpty(statementAttr.Sql)) { var sqlStatement = smartSqlMapper.SmartSqlOptions.SmartSqlContext.GetStatement($"{statementAttr.Scope}.{statementAttr.Id}"); cmdType = sqlStatement.SqlCommandType; if (sqlStatement.MultipleResultMap != null && !returnType.IsValueType) { statementAttr.Execute = ExecuteBehavior.GetNested; return(statementAttr); } } else { cmdType = _commandAnalyzer.Analyse(statementAttr.Sql); } if (returnType == typeof(int) || returnType == _voidType || returnType == null) { statementAttr.Execute = ExecuteBehavior.Execute; if (returnType == typeof(int)) { if (cmdType.HasFlag(SqlCommandType.Select)) { statementAttr.Execute = ExecuteBehavior.ExecuteScalar; } } } else if (returnType.IsValueType || returnType == typeof(string)) { statementAttr.Execute = ExecuteBehavior.ExecuteScalar; if (!cmdType.HasFlag(SqlCommandType.Select)) { statementAttr.Execute = ExecuteBehavior.Execute; } } else { var isQueryEnumerable = typeof(IEnumerable).IsAssignableFrom(returnType); if (isQueryEnumerable) { statementAttr.Execute = ExecuteBehavior.Query; } else { statementAttr.Execute = ExecuteBehavior.QuerySingle; } } } return(statementAttr); }
private void EmitSetSqlId(ILGenerator ilGenerator, StatementAttribute statementAttr) { ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ldstr, statementAttr.Id); ilGenerator.Emit(OpCodes.Call, _set_SqlIdMethod); }
private void EmitSetRealSql(ILGenerator ilGenerator, StatementAttribute statementAttr) { ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ldstr, statementAttr.Sql); ilGenerator.Emit(OpCodes.Call, _set_RealSqlMethod); }
private void BuildMethod(Type interfaceType, TypeBuilder typeBuilder, MethodInfo methodInfo, FieldBuilder sqlMapperField, ISmartSqlMapper smartSqlMapper, string scope) { var methodParams = methodInfo.GetParameters(); var paramTypes = methodParams.Select(m => m.ParameterType).ToArray(); if (paramTypes.Any(p => p.IsGenericParameter)) { _logger.LogError("SmartSql.DyRepository method parameters do not support generic parameters for the time being!"); throw new SmartSqlException("SmartSql.DyRepository method parameters do not support generic parameters for the time being!"); } var returnType = methodInfo.ReturnType; var implMehtod = typeBuilder.DefineMethod(methodInfo.Name , MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final , returnType, paramTypes); var isTaskReturnType = _taskType.IsAssignableFrom(returnType); if (methodInfo.IsGenericMethod) { var genericArgs = methodInfo.GetGenericArguments(); var gArgNames = genericArgs.Select(gArg => gArg.Name).ToArray(); var defineGenericArgs = implMehtod.DefineGenericParameters(gArgNames); for (int i = 0; i < gArgNames.Length; i++) { var genericArg = genericArgs[i]; var defineGenericArg = defineGenericArgs[i]; defineGenericArg.SetGenericParameterAttributes(genericArg.GenericParameterAttributes); } } StatementAttribute statementAttr = PreStatement(interfaceType, scope, methodInfo, returnType, isTaskReturnType, smartSqlMapper); var ilGenerator = implMehtod.GetILGenerator(); ilGenerator.DeclareLocal(_reqContextType); ilGenerator.DeclareLocal(_dbParametersType); if (statementAttr.Execute == ExecuteBehavior.FillMultiple) { ilGenerator.DeclareLocal(_multipleResultType); ilGenerator.Emit(OpCodes.Newobj, _multipleResultImplCtor); ilGenerator.Emit(OpCodes.Stloc_2); } if (paramTypes.Length == 1 && paramTypes.First() == _reqContextType) { ilGenerator.Emit(OpCodes.Ldarg_1); ilGenerator.Emit(OpCodes.Stloc_0); } else { EmitNewRequestContext(ilGenerator); SetCmdTypeAndSourceChoice(statementAttr, ilGenerator); if (String.IsNullOrEmpty(statementAttr.Sql)) { EmitSetScope(ilGenerator, statementAttr.Scope); EmitSetSqlId(ilGenerator, statementAttr); } else { EmitSetRealSql(ilGenerator, statementAttr); } if (paramTypes.Length == 1 && !IsSimpleParam(paramTypes.First())) { ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ldarg_1); ilGenerator.Emit(OpCodes.Call, _set_RequestMethod); } else if (paramTypes.Length > 0) { bool ignoreParameterCase = smartSqlMapper.SmartSqlOptions.SmartSqlContext.IgnoreParameterCase; ilGenerator.Emit(ignoreParameterCase ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); ilGenerator.Emit(OpCodes.Newobj, _dbParametersCtor); ilGenerator.Emit(OpCodes.Stloc_1); for (int i = 0; i < methodParams.Length; i++) { int argIndex = i + 1; var reqParam = methodParams[i]; string reqParamName = reqParam.Name; var paramAttr = reqParam.GetCustomAttribute <ParamAttribute>(); if (paramAttr != null && !String.IsNullOrEmpty(paramAttr.Name)) { reqParamName = paramAttr.Name; } ilGenerator.Emit(OpCodes.Ldloc_1); //[dic] ilGenerator.Emit(OpCodes.Ldstr, reqParamName); //[dic][param-name] EmitUtils.LoadArg(ilGenerator, argIndex); if (reqParam.ParameterType.IsValueType) { ilGenerator.Emit(OpCodes.Box, reqParam.ParameterType); } ilGenerator.Emit(OpCodes.Call, _addDbParamMehtod);//[empty] } ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ldloc_1); ilGenerator.Emit(OpCodes.Call, _set_RequestMethod); } } MethodInfo executeMethod = null; executeMethod = PreExecuteMethod(statementAttr, returnType, isTaskReturnType); ilGenerator.Emit(OpCodes.Ldarg_0); // [this] ilGenerator.Emit(OpCodes.Ldfld, sqlMapperField); //[this][sqlMapper] ilGenerator.Emit(OpCodes.Ldloc_0); //[sqlMapper][requestContext] if (statementAttr.Execute == ExecuteBehavior.FillMultiple) { var returnGenericTypeArguments = returnType.GenericTypeArguments; foreach (var typeArg in returnGenericTypeArguments) { bool isEnum = _enumerableType.IsAssignableFrom(typeArg); var addTypeMapMethod = isEnum ? _multipleResult_AddTypeMap : _multipleResult_AddSingleTypeMap; var realRetType = isEnum ? typeArg.GenericTypeArguments[0] : typeArg; addTypeMapMethod = addTypeMapMethod.MakeGenericMethod(realRetType); ilGenerator.Emit(OpCodes.Ldloc_2); ilGenerator.Emit(OpCodes.Call, addTypeMapMethod); ilGenerator.Emit(OpCodes.Pop); } ilGenerator.Emit(OpCodes.Ldloc_2); } ilGenerator.Emit(OpCodes.Call, executeMethod); if (returnType == _voidType) { ilGenerator.Emit(OpCodes.Pop); } if (statementAttr.Execute == ExecuteBehavior.FillMultiple) { ilGenerator.Emit(OpCodes.Pop); QueryMultipleToValueTuple(methodInfo, returnType, ilGenerator); } ilGenerator.Emit(OpCodes.Ret); if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"RepositoryBuilder.BuildMethod:{methodInfo.Name}->Statement:[Scope:{statementAttr.Scope},Id:{statementAttr.Id},Execute:{statementAttr.Execute},Sql:{statementAttr.Sql},IsAsync:{isTaskReturnType}]"); } }
private void BuildMethod(TypeBuilder typeBuilder, MethodInfo methodInfo, FieldBuilder sqlMapperField, string scope) { var methodParams = methodInfo.GetParameters(); var paramTypes = methodParams.Select(m => m.ParameterType).ToArray(); if (paramTypes.Any(p => p.IsGenericParameter)) { _logger.LogError("SmartSql.DyRepository method parameters do not support generic parameters for the time being!"); throw new SmartSqlException("SmartSql.DyRepository method parameters do not support generic parameters for the time being!"); } var returnType = methodInfo.ReturnType; var implMehtod = typeBuilder.DefineMethod(methodInfo.Name , MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final , returnType, paramTypes); var isTaskReturnType = _taskType.IsAssignableFrom(returnType); if (methodInfo.IsGenericMethod) { var genericArgs = methodInfo.GetGenericArguments(); var gArgNames = genericArgs.Select(gArg => gArg.Name).ToArray(); var defineGenericArgs = implMehtod.DefineGenericParameters(gArgNames); for (int i = 0; i < gArgNames.Length; i++) { var genericArg = genericArgs[i]; var defineGenericArg = defineGenericArgs[i]; defineGenericArg.SetGenericParameterAttributes(genericArg.GenericParameterAttributes); } } StatementAttribute statementAttr = PreStatement(methodInfo, returnType, isTaskReturnType); var ilGenerator = implMehtod.GetILGenerator(); ilGenerator.DeclareLocal(_reqContextType); ilGenerator.DeclareLocal(_reqParamsDicType); if (paramTypes.Length == 1 && paramTypes.First() == _reqContextType) { ilGenerator.Emit(OpCodes.Ldarg_1); ilGenerator.Emit(OpCodes.Stloc_0); } else { EmitNewRequestContext(ilGenerator); if (String.IsNullOrEmpty(statementAttr.Sql)) { EmitSetScope(ilGenerator, scope); EmitSetSqlId(ilGenerator, statementAttr); } else { EmitSetRealSql(ilGenerator, statementAttr); } if (paramTypes.Length == 1 && !IsSimpleParam(paramTypes.First())) { ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ldarg_1); ilGenerator.Emit(OpCodes.Call, _set_RequestMethod); } else if (paramTypes.Length > 0) { ilGenerator.Emit(OpCodes.Newobj, _reqParamsDicCtor); ilGenerator.Emit(OpCodes.Stloc_1); for (int i = 0; i < methodParams.Length; i++) { int argIndex = i + 1; var reqParam = methodParams[i]; if (reqParam.ParameterType == typeof(DataSourceChoice)) { ilGenerator.Emit(OpCodes.Ldloc_0); EmitUtils.LoadArg(ilGenerator, argIndex); ilGenerator.Emit(OpCodes.Call, _set_DataSourceChoiceMethod); continue; } if (reqParam.ParameterType == typeof(CommandType)) { ilGenerator.Emit(OpCodes.Ldloc_0); EmitUtils.LoadArg(ilGenerator, argIndex); ilGenerator.Emit(OpCodes.Call, _set_CommandTypeMethod); continue; } ilGenerator.Emit(OpCodes.Ldloc_1); //[dic] ilGenerator.Emit(OpCodes.Ldstr, reqParam.Name); //[dic][param-name] EmitUtils.LoadArg(ilGenerator, argIndex); if (reqParam.ParameterType.IsValueType) { ilGenerator.Emit(OpCodes.Box, reqParam.ParameterType); } ilGenerator.Emit(OpCodes.Call, _addReqParamMehtod);//[empty] } ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ldloc_1); ilGenerator.Emit(OpCodes.Call, _set_RequestMethod); } } MethodInfo executeMethod = null; executeMethod = PreExecuteMethod(statementAttr, returnType, isTaskReturnType); ilGenerator.Emit(OpCodes.Ldarg_0); // [this] ilGenerator.Emit(OpCodes.Ldfld, sqlMapperField); //[this][sqlMapper] ilGenerator.Emit(OpCodes.Ldloc_0); //[sqlMapper][requestContext] ilGenerator.Emit(OpCodes.Call, executeMethod); if (returnType == _voidType) { ilGenerator.Emit(OpCodes.Pop); } ilGenerator.Emit(OpCodes.Ret); if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"RepositoryBuilder.BuildMethod:{methodInfo.Name}->Statement:[Scope:{scope},Id:{statementAttr.Id},Execute:{statementAttr.Execute},Sql:{statementAttr.Sql},IsAsync:{isTaskReturnType}]"); } }
private void BuildMethod(Type interfaceType, TypeBuilder typeBuilder, MethodInfo methodInfo, FieldBuilder sqlMapperField, SmartSqlConfig smartSqlConfig, string scope) { var methodParams = methodInfo.GetParameters(); var paramTypes = methodParams.Select(m => m.ParameterType).ToArray(); if (paramTypes.Any(p => p.IsGenericParameter)) { _logger.LogError("SmartSql.DyRepository method parameters do not support generic parameters for the time being!"); throw new SmartSqlException("SmartSql.DyRepository method parameters do not support generic parameters for the time being!"); } var returnType = methodInfo.ReturnType; var implMethod = typeBuilder.DefineMethod(methodInfo.Name , MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final , returnType, paramTypes); var isTaskReturnType = CommonType.Task.IsAssignableFrom(returnType); if (methodInfo.IsGenericMethod) { var genericArgs = methodInfo.GetGenericArguments(); var gArgNames = genericArgs.Select(gArg => gArg.Name).ToArray(); var defineGenericArgs = implMethod.DefineGenericParameters(gArgNames); for (int i = 0; i < gArgNames.Length; i++) { var genericArg = genericArgs[i]; var defineGenericArg = defineGenericArgs[i]; defineGenericArg.SetGenericParameterAttributes(genericArg.GenericParameterAttributes); } } StatementAttribute statementAttr = PreStatement(interfaceType, scope, methodInfo, returnType, isTaskReturnType, smartSqlConfig); var ilGen = implMethod.GetILGenerator(); bool onlyOneParam = paramTypes.Length == 1; Type firstParamType = paramTypes.FirstOrDefault(); ilGen.DeclareLocal(RequestContextType.AbstractType); if (onlyOneParam && RequestContextType.AbstractType.IsAssignableFrom(firstParamType)) { throw new SmartSqlException($"DyRepository.Method ParameterType :{firstParamType.FullName} can not be RequestContext."); //ilGen.LoadArg(1); //ilGen.StoreLocalVar(0); } bool isOnlyOneClassParam = onlyOneParam && !IsSimpleParam(firstParamType); EmitNewRequestContext(ilGen, isOnlyOneClassParam, firstParamType); EmitSetCommandType(ilGen, statementAttr); EmitSetDataSourceChoice(ilGen, statementAttr); if (String.IsNullOrEmpty(statementAttr.Sql)) { EmitSetScope(ilGen, statementAttr.Scope); EmitSetSqlId(ilGen, statementAttr); } else { EmitSetRealSql(ilGen, statementAttr); } if (isOnlyOneClassParam) { ilGen.LoadLocalVar(0); ilGen.LoadArg(1); ilGen.Callvirt(RequestContextType.Method.SetRequest); } else if (paramTypes.Length > 0) { ilGen.DeclareLocal(SqlParameterType.SqlParameterCollection); bool ignoreParameterCase = smartSqlConfig.Settings.IgnoreParameterCase; ilGen.Emit(ignoreParameterCase ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); ilGen.New(SqlParameterType.Ctor.SqlParameterCollection); ilGen.StoreLocalVar(1); for (int i = 0; i < methodParams.Length; i++) { int argIndex = i + 1; var reqParam = methodParams[i]; string reqParamName = reqParam.Name; var paramAttr = reqParam.GetCustomAttribute <ParamAttribute>(); if (paramAttr != null && !String.IsNullOrEmpty(paramAttr.Name)) { reqParamName = paramAttr.Name; } ilGen.LoadLocalVar(1); ilGen.LoadString(reqParamName); ilGen.LoadArg(argIndex); if (reqParam.ParameterType.IsValueType) { ilGen.Box(reqParam.ParameterType); } ilGen.LoadType(reqParam.ParameterType); ilGen.New(SqlParameterType.Ctor.SqlParameter); ilGen.Dup(); var getHandlerMethod = paramAttr?.FieldType != null?TypeHandlerCacheType.GetHandlerMethod(reqParam.ParameterType, paramAttr?.FieldType) : PropertyTypeHandlerCacheType.GetHandlerMethod(reqParam.ParameterType); ilGen.Call(getHandlerMethod); ilGen.Call(SqlParameterType.Method.SetTypeHandler); ilGen.Call(SqlParameterType.Method.Add); } ilGen.LoadLocalVar(0); ilGen.LoadLocalVar(1); ilGen.Callvirt(RequestContextType.Method.SetRequest); } MethodInfo executeMethod = PreExecuteMethod(statementAttr, returnType, isTaskReturnType); ilGen.LoadArg(0); ilGen.FieldGet(sqlMapperField); ilGen.LoadLocalVar(0); ilGen.Call(executeMethod); if (returnType == CommonType.Void) { ilGen.Pop(); } ilGen.Return(); if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug($"RepositoryBuilder.BuildMethod:{methodInfo.Name}->Statement:[Scope:{statementAttr.Scope},Id:{statementAttr.Id},Execute:{statementAttr.Execute},Sql:{statementAttr.Sql},IsAsync:{isTaskReturnType}]"); } }
private void EmitSetSqlId(ILGenerator ilGen, StatementAttribute statementAttr) { ilGen.LoadLocalVar(0); ilGen.LoadString(statementAttr.Id); ilGen.Callvirt(RequestContextType.Method.SetSqlId); }
private MethodInfo PreExecuteMethod(StatementAttribute statementAttr, Type returnType, bool isTaskReturnType) { MethodInfo executeMethod; if (isTaskReturnType) { var realReturnType = returnType.GenericTypeArguments.FirstOrDefault(); switch (statementAttr.Execute) { case ExecuteBehavior.Execute: { executeMethod = ISqlMapperType.Method.ExecuteAsync; break; } case ExecuteBehavior.ExecuteScalar: { executeMethod = ISqlMapperType.Method.ExecuteScalarAsync.MakeGenericMethod(realReturnType); break; } case ExecuteBehavior.QuerySingle: { executeMethod = ISqlMapperType.Method.QuerySingleAsync.MakeGenericMethod(realReturnType); break; } case ExecuteBehavior.Query: { var method = ISqlMapperType.Method.QueryAsync; var enumerableType = realReturnType.GenericTypeArguments[0]; executeMethod = method.MakeGenericMethod(enumerableType); break; } case ExecuteBehavior.GetDataTable: { executeMethod = ISqlMapperType.Method.GetDataTableAsync; break; } case ExecuteBehavior.GetDataSet: { executeMethod = ISqlMapperType.Method.GetDataSetAsync; break; } default: { throw new ArgumentException(); } } } else { switch (statementAttr.Execute) { case ExecuteBehavior.Execute: { executeMethod = ISqlMapperType.Method.Execute; break; } case ExecuteBehavior.ExecuteScalar: { executeMethod = ISqlMapperType.Method.ExecuteScalar.MakeGenericMethod(returnType); break; } case ExecuteBehavior.QuerySingle: { executeMethod = ISqlMapperType.Method.QuerySingle.MakeGenericMethod(returnType); break; } case ExecuteBehavior.Query: { var method = ISqlMapperType.Method.Query; var enumerableType = returnType.GenericTypeArguments[0]; executeMethod = method.MakeGenericMethod(new Type[] { enumerableType }); break; } case ExecuteBehavior.GetDataTable: { executeMethod = ISqlMapperType.Method.GetDataTable; break; } case ExecuteBehavior.GetDataSet: { executeMethod = ISqlMapperType.Method.GetDataSet; break; } default: { throw new ArgumentException(); } } } return(executeMethod); }
private StatementAttribute PreStatement(Type interfaceType, string scope, MethodInfo methodInfo, Type returnType, bool isTaskReturnType, SmartSqlConfig smartSqlConfig) { returnType = isTaskReturnType ? returnType.GetGenericArguments().FirstOrDefault() : returnType; var statementAttr = methodInfo.GetCustomAttribute <StatementAttribute>(); var methodName = _sqlIdNamingConvert == null ? methodInfo.Name : _sqlIdNamingConvert.Invoke(interfaceType, methodInfo); if (isTaskReturnType && methodInfo.Name.EndsWith("Async") && _sqlIdNamingConvert == null) { methodName = methodName.Substring(0, methodName.Length - 5); } if (statementAttr != null) { statementAttr.Id = !String.IsNullOrEmpty(statementAttr.Id) ? statementAttr.Id : methodName; statementAttr.Scope = !String.IsNullOrEmpty(statementAttr.Scope) ? statementAttr.Scope : scope; } else { statementAttr = new StatementAttribute { Scope = scope, Id = methodName }; } if (returnType == typeof(DataTable)) { statementAttr.Execute = ExecuteBehavior.GetDataTable; return(statementAttr); } if (returnType == typeof(DataSet)) { statementAttr.Execute = ExecuteBehavior.GetDataSet; return(statementAttr); } if (statementAttr.Execute == ExecuteBehavior.Auto) { Configuration.StatementType statementType = Configuration.StatementType.Unknown; if (String.IsNullOrEmpty(statementAttr.Sql)) { var sqlStatement = smartSqlConfig.GetSqlMap(statementAttr.Scope).GetStatement($"{statementAttr.Scope}.{statementAttr.Id}"); statementType = sqlStatement.StatementType; } else { statementType = _statementAnalyzer.Analyse(statementAttr.Sql); } if (CommonType.IsValueTuple(returnType)) { statementAttr.Execute = ExecuteBehavior.QuerySingle; } else if (returnType == CommonType.Int32 || returnType == CommonType.Void || returnType == null) { statementAttr.Execute = ExecuteBehavior.Execute; if (returnType == CommonType.Int32) { if (statementType.HasFlag(Configuration.StatementType.Select)) { statementAttr.Execute = ExecuteBehavior.ExecuteScalar; } } } else if (returnType.IsValueType || returnType == CommonType.String) { statementAttr.Execute = ExecuteBehavior.ExecuteScalar; if (!statementType.HasFlag(Configuration.StatementType.Select)) { statementAttr.Execute = ExecuteBehavior.Execute; } } else { var isQueryEnumerable = typeof(IEnumerable).IsAssignableFrom(returnType); statementAttr.Execute = isQueryEnumerable ? ExecuteBehavior.Query : ExecuteBehavior.QuerySingle; } } return(statementAttr); }
private Statement PreStatement(Type interfaceType, SqlMap sqlMap, MethodInfo methodInfo, Type returnType, bool isTaskReturnType, out ExecuteBehavior executeBehavior) { var statementAttr = methodInfo.GetCustomAttribute <StatementAttribute>(); var methodName = _sqlIdNamingConvert == null ? methodInfo.Name : _sqlIdNamingConvert.Invoke(interfaceType, methodInfo); if (isTaskReturnType && methodInfo.Name.EndsWith("Async") && _sqlIdNamingConvert == null) { methodName = methodName.Substring(0, methodName.Length - 5); } if (statementAttr != null) { statementAttr.Id = !String.IsNullOrEmpty(statementAttr.Id) ? statementAttr.Id : methodName; } else { statementAttr = new StatementAttribute { Id = methodName }; } var fullSqlId = $"{sqlMap.Scope}.{statementAttr.Id}"; Statement statement; if (String.IsNullOrEmpty(statementAttr.Sql)) { statement = sqlMap.GetStatement(fullSqlId); } else { if (sqlMap.Statements.ContainsKey(fullSqlId)) { throw new SmartSqlException($"Statement.FullSqlId:[{fullSqlId}] already exists!"); } var resultCacheAttr = methodInfo.GetCustomAttribute <ResultCacheAttribute>(); statement = new Statement { SqlMap = sqlMap, Id = statementAttr.Id, StatementType = _statementAnalyzer.Analyse(statementAttr.Sql), SqlTags = new List <ITag> { new SqlText(statementAttr.Sql, sqlMap.SmartSqlConfig.Database.DbProvider.ParameterPrefix) }, CommandType = statementAttr.CommandType, EnablePropertyChangedTrack = statementAttr.EnablePropertyChangedTrack, ReadDb = statementAttr.ReadDb }; if (statementAttr.CommandTimeout > 0) { statement.CommandTimeout = statementAttr.CommandTimeout; } if (statementAttr.SourceChoice != DataSourceChoice.Unknow) { statement.SourceChoice = statementAttr.SourceChoice; } if (resultCacheAttr != null) { statement.CacheId = ParseCacheFullId(sqlMap.Scope, resultCacheAttr.CacheId); statement.Cache = sqlMap.GetCache(statement.CacheId); } sqlMap.Statements.Add(statement.FullSqlId, statement); } returnType = isTaskReturnType ? returnType.GetGenericArguments().FirstOrDefault() : returnType; if (returnType == typeof(DataTable)) { statementAttr.Execute = ExecuteBehavior.GetDataTable; } if (returnType == typeof(DataSet)) { statementAttr.Execute = ExecuteBehavior.GetDataSet; } if (statementAttr.Execute == ExecuteBehavior.Auto) { if (CommonType.IsValueTuple(returnType)) { statementAttr.Execute = ExecuteBehavior.QuerySingle; } else if (returnType == CommonType.Int32 || returnType == CommonType.Void || returnType == null) { statementAttr.Execute = ExecuteBehavior.Execute; if (returnType == CommonType.Int32) { if (statement.StatementType.HasFlag(Configuration.StatementType.Select)) { statementAttr.Execute = ExecuteBehavior.ExecuteScalar; } } } else if (returnType.IsValueType || returnType == CommonType.String) { statementAttr.Execute = ExecuteBehavior.ExecuteScalar; if (!statement.StatementType.HasFlag(Configuration.StatementType.Select)) { statementAttr.Execute = ExecuteBehavior.Execute; } } else { var isQueryEnumerable = typeof(IEnumerable).IsAssignableFrom(returnType); statementAttr.Execute = isQueryEnumerable ? ExecuteBehavior.Query : ExecuteBehavior.QuerySingle; } } executeBehavior = statementAttr.Execute; return(statement); }