Пример #1
0
        /// <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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        /// <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);
                }
            }
        }
Пример #4
0
        /// <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));
        }
Пример #5
0
 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]
 }
Пример #6
0
        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("方法参数类型不匹配!");
        }
Пример #7
0
        /// <summary>
        /// 设置默认值。
        /// </summary>
        /// <param name="defaultValue">默认值。</param>
        public void SetConstant(object defaultValue)
        {
            if (defaultValue is Missing)
            {
                return;
            }

            hasDefaultValue = true;

            this.defaultValue = EmitUtils.SetConstantOfType(defaultValue, RuntimeType);
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
        /// <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);
        }
Пример #10
0
 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);
     }
 }
Пример #11
0
        /// <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}”类型无法默认转换!");
            }
        }
Пример #12
0
        /// <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);
            }
        }
Пример #13
0
        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();
            }
        }
Пример #14
0
        /// <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);
        }
Пример #15
0
 /// <summary>
 /// 生成。
 /// </summary>
 /// <param name="ilg">指令。</param>
 public override void Load(ILGenerator ilg) => EmitUtils.EmitDefaultOfType(ilg, RuntimeType);
Пример #16
0
        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);
        }
Пример #18
0
        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}]");
            }
        }
Пример #19
0
        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}]");
            }
        }
Пример #20
0
 /// <summary>
 /// 生成。
 /// </summary>
 /// <param name="ilg">指令。</param>
 public override void Load(ILGenerator ilg) => EmitUtils.EmitConstantOfType(ilg, value, RuntimeType);
Пример #21
0
        /// <summary>
        /// 设置默认值。
        /// </summary>
        /// <param name="defaultValue">默认值。</param>
        public void SetConstant(object defaultValue)
        {
            hasDefaultValue = true;

            this.defaultValue = EmitUtils.SetConstantOfType(defaultValue, RuntimeType);
        }
Пример #22
0
        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));
        }