Example #1
0
        public MergableMethod Emit()
        {
            var instructions = new List <Instruction>();

            // if the callback is an instance method then add in the instance (this)
            if (!_method.IsStatic)
            {
                instructions.AddRange(AnonymousExtensions.ParseAnonymousInstruction(
                                          new { OpCodes.Ldarg_0 }
                                          ));
            }

            foreach (var parameter in _method.Parameters)
            {
                var opcode = parameter.ParameterType.IsByReference ? OpCodes.Ldarga : OpCodes.Ldarg;

                instructions.AddRange(AnonymousExtensions.ParseAnonymousInstruction(
                                          new { opcode, parameter }
                                          ));
            }

            instructions.AddRange(AnonymousExtensions.ParseAnonymousInstruction(
                                      new { OpCodes.Call, _method }
                                      ));

            if (_method.ReturnType.FullName != "System.Void")
            {
                instructions.AddRange(AnonymousExtensions.ParseAnonymousInstruction(
                                          new { OpCodes.Pop }
                                          ));
            }

            return(new MergableMethod()
            {
                Instructions = instructions
            });
        }
        List <Instruction> EmitCall()
        {
            var invoke_method = _hook_field.FieldType.Resolve().Method("Invoke");

            VariableDefinition
                local_field_instance = new VariableDefinition(invoke_method.ReturnType)
            ;

            InstructionReference
                call_invoke  = new InstructionReference(),
                store_result = new InstructionReference()
            ;

            bool has_return_type = invoke_method.ReturnType.FullName != "System.Void";

            if (this._is_cancellable)
            {
                _variables.Add(local_field_instance);
                return(AnonymousExtensions.ParseAnonymousInstruction(
                           new { OpCodes.Ldsfld, _hook_field },
                           new { OpCodes.Dup },
                           new { OpCodes.Brtrue_S, call_invoke },

                           new { OpCodes.Pop },
                           new { OpCodes.Ldc_I4_1 },
                           new { OpCodes.Br_S, store_result },

                           new Func <IEnumerable <object> >(() =>
                {
                    IEnumerable <object> collection = null;

                    if (this._parameters.Count() > 0)
                    {
                        var first = this._parameters.First();
                        call_invoke = call_invoke.Create(
                            _is_by_reference && first.ParameterType.IsValueType ? OpCodes.Ldarga : OpCodes.Ldarg,
                            first
                            );
                        collection = new object[]
                        {
                            call_invoke,
                            this._parameters.Skip(1)
                            .Select(x => new {
                                OpCode = _is_by_reference && x.ParameterType.IsValueType ? OpCodes.Ldarga : OpCodes.Ldarg,
                                Operand = x
                            }),

                            // adds the return result
                            new Func <IEnumerable <object> >(() =>
                            {
                                if (_result_variable != null)
                                {
                                    return new [] {
                                        new {
                                            OpCode = _is_by_reference ? OpCodes.Ldloca : OpCodes.Ldloc,
                                            _result_variable
                                        }
                                    };
                                }
                                return Enumerable.Empty <object>();
                            }).Invoke(),

                            new { OpCodes.Callvirt, invoke_method }
                        };
                    }
                    else
                    {
                        collection = new object[]
                        {
                            // adds the return result
                            new Func <IEnumerable <object> >(() =>
                            {
                                if (_result_variable != null)
                                {
                                    return new object [] {
                                        call_invoke = call_invoke.Create(
                                            _is_by_reference ? OpCodes.Ldloca : OpCodes.Ldloc,
                                            _result_variable
                                            ),

                                        new { OpCodes.Callvirt, invoke_method }
                                    };
                                }
                                else
                                {
                                    return new []
                                    {
                                        call_invoke = call_invoke.Create(OpCodes.Callvirt, invoke_method)
                                    };
                                }
                            }).Invoke()
                        };
                    }

                    return collection;
                }).Invoke(),

                           store_result = store_result.Create(OpCodes.Stloc, local_field_instance),
                           new
                {
                    OpCodes.Ldloc,
                    local_field_instance
                }
                           ).ToList());
            }
            else
            {
                return(AnonymousExtensions.ParseAnonymousInstruction(
                           new { OpCodes.Ldsfld, _hook_field },
                           new { OpCodes.Dup },
                           new { OpCodes.Brtrue_S, call_invoke },

                           new { OpCodes.Pop },
                           new { OpCodes.Br_S, store_result },

                           new Func <IEnumerable <object> >(() =>
                {
                    IEnumerable <object> collection = null;

                    if (this._parameters.Count() > 0)
                    {
                        var first = this._parameters.First();
                        call_invoke = call_invoke.Create(
                            _is_by_reference && first.ParameterType.IsValueType ? OpCodes.Ldarga : OpCodes.Ldarg,
                            first

                            );
                        collection = new object[]
                        {
                            call_invoke,
                            this._parameters.Skip(1)
                            .Select(x => new {
                                OpCode = _is_by_reference && x.ParameterType.IsValueType? OpCodes.Ldarga : OpCodes.Ldarg,
                                Operand = x
                            }),

                            // adds the return result
                            new Func <IEnumerable <object> >(() =>
                            {
                                if (_result_variable != null)
                                {
                                    return new [] {
                                        new {
                                            OpCode = _is_by_reference ? OpCodes.Ldloca : OpCodes.Ldloc,
                                            _result_variable
                                        }
                                    };
                                }
                                return Enumerable.Empty <object>();
                            }).Invoke(),

                            //new { OpCodes.Callvirt, invoke_method }


                            new Func <IEnumerable <object> >(() =>
                            {
                                IEnumerable <object> res = new [] {
                                    new { OpCodes.Callvirt, invoke_method }
                                };

                                if (has_return_type)
                                {
                                    res = res.Concat(new[]
                                    {
                                        new { OpCodes.Pop }
                                    });
                                }

                                return res;
                            }).Invoke()
                        };
                    }
                    else
                    {
                        //collection = new object[]
                        //{
                        //	new Func<IEnumerable<object>>(() =>
                        //	{
                        //		IEnumerable<object> res;
                        if (_result_variable != null)
                        {
                            collection = new object[] {
                                call_invoke = call_invoke.Create(
                                    _is_by_reference ? OpCodes.Ldloca : OpCodes.Ldloc,
                                    _result_variable
                                    ),

                                new { OpCodes.Callvirt, invoke_method }
                            };
                        }
                        else
                        {
                            collection = new[]
                            {
                                call_invoke = call_invoke.Create(OpCodes.Callvirt, invoke_method)
                            };
                        }

                        if (has_return_type)
                        {
                            collection = collection.Concat(new[]
                            {
                                new { OpCodes.Pop }
                            });
                        }

                        //		return res;
                        //	}).Invoke()
                        //};
                    }

                    return collection;
                }).Invoke(),

                           store_result = store_result.Create(
                               OpCodes.Nop                  // invoke_method.ReturnType.FullName == "System.Void" ? OpCodes.Nop : OpCodes.Pop
                               )
                           ).ToList());
            }
        }