예제 #1
0
        public MethodBuilder DefineMethod(
            string methodName,
            ParameterExpression[] paramExprs,
            Expression bodyExpr,
            MethodAttributes methodAttributes     = MethodAttributes.Public | MethodAttributes.Virtual,
            CallingConventions callingConventions = CallingConventions.Standard | CallingConventions.HasThis)
        {
            if (paramExprs == null)
            {
                paramExprs = Array.Empty <ParameterExpression>();
            }

            Type[]   paramTypes = new Type[paramExprs.Length];
            string[] paramNames = new string[paramExprs.Length];

            for (int i = 0; i < paramExprs.Length; i++)
            {
                paramTypes[i] = paramExprs[i].Type;
                paramNames[i] = paramExprs[i].Name;
            }

            if (callingConventions.HasFlag(CallingConventions.HasThis))
            {
                ParameterExpression[] newParams = new ParameterExpression[paramExprs.Length + 1];
                newParams[0] = This;
                Array.Copy(paramExprs, 0, newParams, 1, paramExprs.Length);
                paramExprs = newParams;
            }

            MethodBuilder newMethod = TypeBuilder.DefineMethod(
                methodName,
                methodAttributes,
                callingConventions,
                bodyExpr.Type,
                paramTypes);

            for (int i = 0; i < paramTypes.Length; i++)
            {
                newMethod.DefineParameter(i, ParameterAttributes.None, paramNames[i]);
            }

            bool success = ExpressionCompiler.CompileForTypeBuilder(paramExprs, bodyExpr, bodyExpr.Type, newMethod.GetILGenerator(), true);

            if (!success)
            {
                throw new InvalidOperationException($"Can't compile method");
            }

            Methods.Add(new RuntimeTypeMethod(methodName, newMethod, paramTypes, bodyExpr.Type));

            return(newMethod);
        }