예제 #1
0
        private void BuildMethod(
            TypeBuilder builder, ILGenerator gen, MethodBodyReader reader, Type[] realParameters,
            Dictionary <string, FieldBuilder> fields, Dictionary <string, InterimMethod> methods, string memberName)
        {
            var fakeParameters = reader.Method.GetParameters().Skip(1).Select(p => p.ParameterType).ToArray();
            var fakeReturn     = (reader.Method as MethodInfo)?.ReturnType;

            var writer = new MethodBodyBuilder(gen);

            var locals = reader.Locals.Select(lc => lc.LocalType);

            writer.DeclareLocals(locals);
            writer.DeclareExceptionHandlers(reader.ExceptionHandlers);

            // transforms all ldarg.x to ldarg.x-1 and output the index of the new ldarg.0's (context calls)
            int[] contexts;
            var   body = TransformLdArgOpcodes(reader.Instructions, realParameters, fakeParameters, out contexts);

            // starts at the innermost context call and walks back to the beginning replacing them.
            foreach (var startIndex in contexts.OrderByDescending(x => x))
            {
                var endIndex = startIndex;
                while (endIndex < body.Length)
                {
                    endIndex++;
                    var endOp = body[endIndex];
                    if (endOp.OpCode == OpCodes.Callvirt && DynamicClassContext.Methods.Contains(endOp.Operand as MethodInfo))
                    {
                        break;
                    }
                }

                endIndex++;
                var ins = body.Skip(startIndex).Take(endIndex - startIndex).ToArray();
                ins  = ProcessLdContextInstruction(ins, fields, methods, memberName);
                body = body.Take(startIndex).Concat(ins).Concat(body.Skip(endIndex)).ToArray();
            }


            var returnType = methods.ContainsKey(memberName) ? methods[memberName].Builder.ReturnType : null;

            if (returnType?.IsValueType == true && returnType != typeof(void) && fakeReturn != returnType)
            {
                var lbody = body.ToList();
                // unbox any return values
                foreach (var ret in lbody.Select((s, i) => new { Index = i, Instruction = s }).Where(o => o.Instruction.OpCode == OpCodes.Ret).OrderByDescending(inf => inf.Index).ToArray())
                {
                    lbody.Insert(ret.Index, new Instruction(-1, OpCodes.Unbox_Any)
                    {
                        Operand = returnType
                    });
                }
                writer.EmitBody(lbody);
            }
            else
            {
                writer.EmitBody(body);
            }
        }
예제 #2
0
        public static void BuildFromExistingMethod(string newMethodName, MethodInfo originalMethod, TypeBuilder builder)
        {
            var tMethod = builder.DefineMethod(newMethodName, originalMethod.Attributes, originalMethod.CallingConvention,
                originalMethod.ReturnType, originalMethod.GetParameters().Select(p => p.ParameterType).ToArray());

            var reader = MethodBodyReader.Read(originalMethod);

            MethodBodyBuilder bb = new MethodBodyBuilder(tMethod);
            bb.DeclareLocals(reader.Locals.Select(l => l.LocalType));
            bb.DeclareExceptionHandlers(reader.ExceptionHandlers);
            bb.EmitBody(reader.Instructions);
        }
예제 #3
0
        public static void BuildFromExistingMethod(string newMethodName, MethodInfo originalMethod, TypeBuilder builder)
        {
            var tMethod = builder.DefineMethod(newMethodName, originalMethod.Attributes, originalMethod.CallingConvention,
                                               originalMethod.ReturnType, originalMethod.GetParameters().Select(p => p.ParameterType).ToArray());

            var reader = MethodBodyReader.Read(originalMethod);

            MethodBodyBuilder bb = new MethodBodyBuilder(tMethod.GetILGenerator());

            bb.DeclareLocals(reader.Locals.Select(l => l.LocalType));
            bb.DeclareExceptionHandlers(reader.ExceptionHandlers);
            bb.EmitBody(reader.Instructions);
        }