/// <summary> /// 赋值。 /// </summary> /// <param name="ilg">指令。</param> /// <param name="value">值。</param> protected override void Assign(ILGenerator ilg, AstExpression value) { if (index == -1) { var local = ilg.DeclareLocal(typeof(int)); indexExp.Load(ilg); ilg.Emit(OpCodes.Stloc, local); array.Load(ilg); ilg.Emit(OpCodes.Ldc_I4, local); } else { array.Load(ilg); EmitUtils.EmitInt(ilg, index); } value.Load(ilg); EmitEnsureArrayIndexAssignedSafely(ilg, RuntimeType); }
private static void QueryMultipleToValueTuple(MethodInfo methodInfo, Type returnType, ILGenerator ilGenerator) { var returnGenericTypeArguments = returnType.GenericTypeArguments; var createVT = _valueTupleType.GetMethods().First(m => { if (m.Name != "Create") { return(false); } return(m.GetParameters().Length == returnGenericTypeArguments.Length); }).MakeGenericMethod(returnGenericTypeArguments); if (returnGenericTypeArguments.Length > 8) { throw new SmartSqlException($"SmartSql.DyRepository method:{methodInfo.Name} return type ValueTuple More than 8!"); } var resultIndex = 0; foreach (var typeArg in returnGenericTypeArguments) { bool isEnum = _enumerableType.IsAssignableFrom(typeArg); var getMethod = isEnum ? _multipleResult_Get : _multipleResult_GetSingle; var realRetType = isEnum ? typeArg.GenericTypeArguments[0] : typeArg; getMethod = getMethod.MakeGenericMethod(realRetType); ilGenerator.Emit(OpCodes.Ldloc_2); EmitUtils.LoadInt32(ilGenerator, resultIndex); ilGenerator.Emit(OpCodes.Call, getMethod); resultIndex++; } ilGenerator.Emit(OpCodes.Call, createVT); }
/// <summary> /// 加载数据。 /// </summary> /// <param name="ilg">指令。</param> public override void Load(ILGenerator ilg) { methodAst.Load(ilg); if (instanceAst is null) { ilg.Emit(OpCodes.Ldnull); } else { instanceAst.Load(ilg); } arguments.Load(ilg); ilg.Emit(OpCodes.Callvirt, InvokeMethod); if (RuntimeType != typeof(object)) { if (RuntimeType == typeof(void)) { ilg.Emit(OpCodes.Pop); } else { EmitUtils.EmitConvertToType(ilg, typeof(object), RuntimeType.IsByRef ? RuntimeType.GetElementType() : RuntimeType, true); } } }
/// <summary> /// 设置属性标记。 /// </summary> /// <param name="attributeData">属性。</param> public void SetCustomAttribute(CustomAttributeData attributeData) { if (attributeData is null) { throw new ArgumentNullException(nameof(attributeData)); } customAttributes.Add(EmitUtils.CreateCustomAttribute(attributeData)); }
private void EmitGetTypeHanderValue(ILGenerator iLGenerator, int colIndex, string typeHandlerName, Type propertyType) { iLGenerator.Emit(OpCodes.Ldarg_1);// [RequestContext] iLGenerator.Emit(OpCodes.Ldstr, typeHandlerName);// [RequestContext][typeHandlerName] iLGenerator.Emit(OpCodes.Call, _getTypeHandlerMethod);//[ITypeHandler] iLGenerator.Emit(OpCodes.Ldarg_0);//[typeHandler][dataReader] EmitUtils.LoadInt32(iLGenerator, colIndex);// [typeHandler][dataReader][index] EmitUtils.TypeOf(iLGenerator, propertyType);//[typeHandler][dataReader][index][propertyType] iLGenerator.Emit(OpCodes.Call, TypeUtils.GetValueMethod_TypeHandler);// [property-Value] }
private static Type GetReturnType(AstExpression instanceAst, MethodInfo methodInfo, AstExpression[] arguments) { if (methodInfo is null) { throw new ArgumentNullException(nameof(methodInfo)); } if (arguments is null) { throw new ArgumentNullException(nameof(arguments)); } if (methodInfo.IsStatic ^ (instanceAst is null)) { if (methodInfo.IsStatic) { throw new AstException($"方法“{methodInfo.Name}”是静态的,不能指定实例!"); } else { throw new AstException($"方法“{methodInfo.Name}”不是静态的,必须指定实例!"); } } var parameterInfos = methodInfo.IsGenericMethod ? methodInfo.GetGenericMethodDefinition() .GetParameters() : methodInfo.GetParameters(); if (arguments.Length != parameterInfos.Length) { throw new AstException("方法参数不匹配!"); } if (methodInfo is DynamicMethod dynamicMethod) { if (parameterInfos.Zip(arguments, (x, y) => { return(EmitUtils.EqualSignatureTypes(x.ParameterType, y.RuntimeType) || x.ParameterType.IsAssignableFrom(y.RuntimeType)); }).All(x => x)) { return(dynamicMethod.ReturnType); } } else if (parameterInfos.Zip(arguments, (x, y) => { return(x.ParameterType == y.RuntimeType || x.ParameterType.IsAssignableFrom(y.RuntimeType)); }).All(x => x)) { return(methodInfo.ReturnType); } throw new AstException("方法参数类型不匹配!"); }
/// <summary> /// 设置默认值。 /// </summary> /// <param name="defaultValue">默认值。</param> public void SetConstant(object defaultValue) { if (defaultValue is Missing) { return; } hasDefaultValue = true; this.defaultValue = EmitUtils.SetConstantOfType(defaultValue, RuntimeType); }
/// <summary> /// 实例。 /// </summary> /// <param name="constant">常量。</param> public ICaseHandler Case(ConstantAst constant) { if (constant is null) { throw new ArgumentNullException(nameof(constant)); } IPrivateCaseHandler handler; switch (switchValueKind) { case MySwitchValueKind.Arithmetic when IsArithmetic(constant.RuntimeType): handler = new SwitchCaseArithmeticAst(constant, RuntimeType); break; case MySwitchValueKind.RuntimeType: throw new AstException("当前流程控制为类型转换,请使用“{Case(VariableAst variable)}”方法处理!"); case MySwitchValueKind.Equality: var types = new Type[2] { switchValueType, constant.RuntimeType }; MethodInfo comparison = switchValueType.GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, types, null); if (comparison is null && !EmitUtils.AreEquivalent(switchValueType, constant.RuntimeType)) { comparison = constant.RuntimeType.GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, types, null); } if (comparison is null && switchValueType.IsAssignableFrom(typeof(IEquatable <>).MakeGenericType(constant.RuntimeType))) { comparison = switchValueType.GetMethod("Equals", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { constant.RuntimeType }, null); } if (comparison is null) { throw new InvalidOperationException($"未找到“{constant.RuntimeType}”和“{switchValueType}”有效的比较函数!"); } handler = new SwitchCaseEqualityAst(constant, comparison, RuntimeType); break; default: throw new NotSupportedException(); } switchCases.Add(handler); return(handler); }
/// <summary> /// 取值。 /// </summary> /// <param name="ilg">指令。</param> public override void Load(ILGenerator ilg) { array.Load(ilg); if (index == -1) { indexExp.Load(ilg); } else { EmitUtils.EmitInt(ilg, index); } EmitEnsureArrayIndexLoadedSafely(ilg, RuntimeType); }
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); } }
/// <summary> /// 流程。 /// </summary> public SwitchAst(AstExpression switchValue, AstExpression defaultAst, Type returnType) : this(switchValue, returnType) { if (defaultAst is null) { throw new ArgumentNullException(nameof(defaultAst)); } if (returnType == typeof(void) || EmitUtils.EqualSignatureTypes(defaultAst.RuntimeType, returnType) || defaultAst.RuntimeType.IsAssignableFrom(RuntimeType)) { this.defaultAst = defaultAst; } else { throw new NotSupportedException($"默认模块“{defaultAst.RuntimeType}”和返回“{returnType}”类型无法默认转换!"); } }
/// <summary> /// 加载数据。 /// </summary> /// <param name="ilg">指令。</param> public override void Load(ILGenerator ilg) { bool isObjectElememt = elementType == typeof(object); EmitUtils.EmitInt(ilg, expressions.Length); ilg.Emit(OpCodes.Newarr, elementType); for (int i = 0; i < expressions.Length; i++) { var expressionAst = expressions[i]; ilg.Emit(OpCodes.Dup); EmitUtils.EmitInt(ilg, i); expressionAst.Load(ilg); if (isObjectElememt) { var type = expressionAst.RuntimeType; if (type.IsByRef) { type = type.GetElementType(); } if (type.IsGenericParameter) { ilg.Emit(OpCodes.Box, type); } else if (type.IsValueType) { if (type.IsEnum) { type = Enum.GetUnderlyingType(type); } ilg.Emit(OpCodes.Box, type); } } ilg.Emit(OpCodes.Stelem_Ref); } }
private static void TryEmitConstantOne(ILGenerator ilg, Type type) { switch (Type.GetTypeCode(type.IsEnum ? Enum.GetUnderlyingType(type) : type)) { case TypeCode.Byte: EmitUtils.EmitByte(ilg, 1); break; case TypeCode.Int16: EmitUtils.EmitInt16(ilg, 1); break; case TypeCode.UInt16: EmitUtils.EmitUInt16(ilg, 1); break; case TypeCode.Int32: EmitUtils.EmitInt(ilg, 1); break; case TypeCode.UInt32: EmitUtils.EmitUInt(ilg, 1); break; case TypeCode.Int64: EmitUtils.EmitLong(ilg, 1L); break; case TypeCode.UInt64: EmitUtils.EmitULong(ilg, 1uL); break; case TypeCode.Single: EmitUtils.EmitSingle(ilg, 1F); break; case TypeCode.Double: EmitUtils.EmitDouble(ilg, 1D); break; default: throw new NotSupportedException(); } }
/// <summary> /// 生成。 /// </summary> /// <param name="ilg">指令。</param> public override void Load(ILGenerator ilg) { body.Load(ilg); Type typeFrom = body.RuntimeType; if (typeFrom == RuntimeType) { return; } if (RuntimeType == typeof(void)) { ilg.Emit(OpCodes.Pop); return; } EmitUtils.EmitConvertToType(ilg, typeFrom, RuntimeType.IsByRef ? RuntimeType.GetElementType() : RuntimeType, true); }
/// <summary> /// 生成。 /// </summary> /// <param name="ilg">指令。</param> public override void Load(ILGenerator ilg) => EmitUtils.EmitDefaultOfType(ilg, RuntimeType);
private void EmitLoadColVal(ILGenerator iLGenerator, IDataReader dataReader, int colIndex, string typeHandler, Type toType, Label? isDbNullLabel) { var fieldType = dataReader.GetFieldType(colIndex); if (!String.IsNullOrEmpty(typeHandler)) { if (isDbNullLabel != null) { iLGenerator.Emit(OpCodes.Ldloc_0);// [target] } EmitGetTypeHanderValue(iLGenerator, colIndex, typeHandler, toType); if (toType.IsValueType) { iLGenerator.Emit(OpCodes.Unbox_Any, toType); } } else { var nullUnderType = Nullable.GetUnderlyingType(toType); var realType = nullUnderType ?? toType; if (nullUnderType != null || realType == TypeUtils.StringType) { iLGenerator.Emit(OpCodes.Ldarg_0);// [dataReader] EmitUtils.LoadInt32(iLGenerator, colIndex);// [dataReader][index] iLGenerator.Emit(OpCodes.Call, TypeUtils.IsDBNullMethod);//[isDbNull-value] if (isDbNullLabel != null) { iLGenerator.Emit(OpCodes.Brtrue, isDbNullLabel.Value);//[empty] } else { iLGenerator.Emit(OpCodes.Ldnull); } } var getRealValueMethod = GetRealValueMethod(fieldType); if (isDbNullLabel != null) { iLGenerator.Emit(OpCodes.Ldloc_0);// [target] } if (realType.IsEnum) { EmitUtils.TypeOf(iLGenerator, realType);//[target][enumType] } #region GetValue iLGenerator.Emit(OpCodes.Ldarg_0);// [dataReader] EmitUtils.LoadInt32(iLGenerator, colIndex);// [dataReader][index] if (getRealValueMethod != null) { iLGenerator.Emit(OpCodes.Call, getRealValueMethod);//[prop-value] } else { iLGenerator.Emit(OpCodes.Call, TypeUtils.GetValueMethod_DataRecord);//[prop-value] if (fieldType.IsValueType) { iLGenerator.Emit(OpCodes.Unbox_Any, fieldType); } } #endregion GetValue //[target][property-Value] if (realType.IsEnum) { //[target][propertyType-enumType][property-Value] EmitConvertEnum(iLGenerator, fieldType); iLGenerator.Emit(OpCodes.Unbox_Any, realType); //[target][property-Value(enum-value)] } else if (fieldType != realType) { EmitUtils.ChangeType(iLGenerator, fieldType, realType); } if (nullUnderType != null) { iLGenerator.Emit(OpCodes.Newobj, toType.GetConstructor(new[] { nullUnderType })); } } }
public static System.Func <object, object[], object> CreateDelegate(System.Reflection.MethodInfo methodInfo, bool validateArguments = true, string methodName = null) { if (methodInfo == null) { throw new System.ArgumentNullException(nameof(methodInfo)); } var args = methodInfo.GetParameters(); var dynamicMethod = EmitUtils.CreateDynamicMethod(string.Format("{0}_{1}|{2}", "$Call", methodInfo.Name, methodName), typeof(object), new[] { typeof(object), typeof(object[]) }, methodInfo.DeclaringType); var il = dynamicMethod.GetILGenerator(); var lableValidationCompleted = il.DefineLabel(); if (!validateArguments || (methodInfo.IsStatic && args.Length == 0)) { il.Br_S(lableValidationCompleted); } else { var lableCheckArgumentsRef = il.DefineLabel(); var lableCheckArgumentsLength = il.DefineLabel(); if (!methodInfo.IsStatic) { il.Ldarg_0(); il.Brtrue_S(args.Length > 0 ? lableCheckArgumentsRef : lableValidationCompleted); il.ThrowArgumentsNullExcpetion("instance"); } if (args.Length > 0) { il.MarkLabel(lableCheckArgumentsRef); il.Ldarg_1(); il.Brtrue_S(lableCheckArgumentsLength); il.ThrowArgumentsNullExcpetion("arguments"); il.MarkLabel(lableCheckArgumentsLength); il.Ldarg_1(); il.Ldlen(); il.Conv_I4(); il.LoadInt32(args.Length); il.Bge_S(lableValidationCompleted); il.ThrowArgumentsExcpetion("Not enough arguments in the argument array.", "arguments"); } } il.MarkLabel(lableValidationCompleted); if (!methodInfo.IsStatic) { il.Ldarg_0(); il.CastReference(methodInfo.DeclaringType); } if (args.Length > 0) { for (int i = 0; i < args.Length; i++) { il.Ldarg_1(); il.LoadInt32(i); il.Ldelem_Ref(); il.CastValue(args[i].ParameterType); } } il.CallMethod(methodInfo); if (methodInfo.ReturnType == typeof(void)) { il.Ldc_I4_0(); } else { il.BoxIfNeeded(methodInfo.ReturnType); } il.Ret(); var methodDelegate = dynamicMethod.CreateDelegate(typeof(System.Func <object, object[], object>)); return((System.Func <object, object[], object>)methodDelegate); }
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}]"); } }
/// <summary> /// 生成。 /// </summary> /// <param name="ilg">指令。</param> public override void Load(ILGenerator ilg) => EmitUtils.EmitConstantOfType(ilg, value, RuntimeType);
/// <summary> /// 设置默认值。 /// </summary> /// <param name="defaultValue">默认值。</param> public void SetConstant(object defaultValue) { hasDefaultValue = true; this.defaultValue = EmitUtils.SetConstantOfType(defaultValue, RuntimeType); }
private Func <IDataReader, RequestContext, object> CreateParserImpl(IDataReader dataReader, RequestContext context, Type targetType) { var dynamicMethod = new DynamicMethod("Deserialize" + Guid.NewGuid().ToString("N"), targetType, new[] { TypeUtils.DataReaderType, TypeUtils.RequestContextType }, targetType, true); var iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.DeclareLocal(targetType); var targetCtor = targetType.GetConstructor(Type.EmptyTypes); iLGenerator.Emit(OpCodes.Newobj, targetCtor); // [target] iLGenerator.Emit(OpCodes.Stloc_0); var columnNames = Enumerable.Range(0, dataReader.FieldCount).Select(i => dataReader.GetName(i)).ToArray(); int colIndex = -1; var properties = targetType.GetProperties(); foreach (var colName in columnNames) { colIndex++; var result = context.Statement?.ResultMap?.Results?.FirstOrDefault(r => r.Column == colName); bool hasTypeHandler = result?.Handler != null; string propertyName = result != null ? result.Property : colName; var property = properties.FirstOrDefault(x => string.Compare(x.Name, propertyName, true) == 0); if (property == null) { continue; } if (!property.CanWrite) { continue; } var fieldType = dataReader.GetFieldType(colIndex); Type propertyType = property.PropertyType; Label isDbNullLabel = iLGenerator.DefineLabel(); if (hasTypeHandler) { iLGenerator.Emit(OpCodes.Ldloc_0);// [target] EmitGetTypeHanderValue(iLGenerator, colIndex, propertyName, propertyType); if (propertyType.IsValueType) { iLGenerator.Emit(OpCodes.Unbox_Any, propertyType); } //else //{ // iLGenerator.Emit(OpCodes.Castclass, propertyType); //} } else { var nullUnderType = Nullable.GetUnderlyingType(propertyType); var realType = nullUnderType ?? propertyType; if (nullUnderType != null || realType == TypeUtils.StringType) { iLGenerator.Emit(OpCodes.Ldarg_0); // [dataReader] EmitUtils.LoadInt32(iLGenerator, colIndex); // [dataReader][index] iLGenerator.Emit(OpCodes.Call, TypeUtils.IsDBNullMethod); //[isDbNull-value] iLGenerator.Emit(OpCodes.Brtrue, isDbNullLabel); //[empty] } var getRealValueMethod = GetRealValueMethod(fieldType); iLGenerator.Emit(OpCodes.Ldloc_0);// [target] if (realType.IsEnum) { EmitUtils.TypeOf(iLGenerator, realType);//[target][enumType] } #region GetValue iLGenerator.Emit(OpCodes.Ldarg_0); // [dataReader] EmitUtils.LoadInt32(iLGenerator, colIndex); // [dataReader][index] if (getRealValueMethod != null) { iLGenerator.Emit(OpCodes.Call, getRealValueMethod);//[prop-value] } else { iLGenerator.Emit(OpCodes.Call, TypeUtils.GetValueMethod_DataRecord);//[prop-value] if (fieldType.IsValueType) { iLGenerator.Emit(OpCodes.Unbox_Any, fieldType); } } #endregion //[target][property-Value] if (realType.IsEnum) { //[target][propertyType-enumType][property-Value] EmitConvertEnum(iLGenerator, fieldType); iLGenerator.Emit(OpCodes.Unbox_Any, realType); //[target][property-Value(enum-value)] } else if (fieldType != realType) { EmitUtils.ChangeType(iLGenerator, fieldType, realType); } if (nullUnderType != null) { iLGenerator.Emit(OpCodes.Newobj, propertyType.GetConstructor(new[] { nullUnderType })); } } iLGenerator.Emit(OpCodes.Call, property.SetMethod);// stack is empty iLGenerator.MarkLabel(isDbNullLabel); } iLGenerator.Emit(OpCodes.Ldloc_0);// stack is [rval] iLGenerator.Emit(OpCodes.Ret); var funcType = System.Linq.Expressions.Expression.GetFuncType(TypeUtils.DataReaderType, TypeUtils.RequestContextType, targetType); return((Func <IDataReader, RequestContext, object>)dynamicMethod.CreateDelegate(funcType)); }