public void Register(ITypeHandler typeHandler) { if (!_typeHandlerMap.TryGetValue(typeHandler.PropertyType, out var fieldTypeHandlerMap)) { fieldTypeHandlerMap = new Dictionary <Type, ITypeHandler>(); _typeHandlerMap.Add(typeHandler.PropertyType, fieldTypeHandlerMap); } if (fieldTypeHandlerMap.ContainsKey(typeHandler.FieldType)) { fieldTypeHandlerMap[typeHandler.FieldType] = typeHandler; } else { fieldTypeHandlerMap.Add(typeHandler.FieldType, typeHandler); } TypeHandlerCacheType.SetHandler(typeHandler); PropertyTypeHandlerCacheType.SetHandler(typeHandler); }
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}]"); } }