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()); } }