Type CreateDelegateType(MethodInfo delegateMethod) { var args = delegateMethod.GetParameters(); TypeBuilder tb = NetHelpers.DefineGlobalType("$DelegateHelper"); FieldBuilder meth = tb.DefineField("meth", typeof(ILuaValue), FieldAttributes.Private); FieldBuilder E = tb.DefineField("E", typeof(ILuaEnvironment), FieldAttributes.Private); MethodBuilder mb = NetHelpers.CloneMethod(tb, "Do", delegateMethod); ILGenerator gen = mb.GetILGenerator(); // loc = new object[{args.Length}]; LocalBuilder loc = gen.CreateArray(typeof(object), args.Length); for (int i = 0; i < args.Length; i++) { // loc[i] = arg_{i+1}; gen.Emit(OpCodes.Ldloc, loc); gen.Emit(OpCodes.Ldc_I4, i); gen.Emit(OpCodes.Ldarg, i + 1); if (args[i].ParameterType.IsValueType) { gen.Emit(OpCodes.Box, args[i].ParameterType); } gen.Emit(OpCodes.Stelem, typeof(object)); } // ILuaMultiValue methodArgs = E.Runtime.CreateMultiValueFromObj(loc); LocalBuilder methodArgs = gen.DeclareLocal(typeof(ILuaMultiValue)); gen.Emit(OpCodes.Ldfld, E); gen.Emit(OpCodes.Callvirt, typeof(ILuaEnvironment).GetProperty(nameof(ILuaEnvironment.Runtime)).GetGetMethod()); gen.Emit(OpCodes.Ldloc, loc); gen.Emit(OpCodes.Callvirt, typeof(ILuaRuntime).GetMethod(nameof(ILuaRuntime.CreateMultiValueFromObj))); gen.Emit(OpCodes.Stloc, methodArgs); // ret = this.meth.Invoke(LuaNil.Nil, false, -1, methodArgs) LocalBuilder ret = gen.DeclareLocal(typeof(ILuaMultiValue)); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldfld, meth); gen.Emit(OpCodes.Ldnull); gen.Emit(OpCodes.Ldfld, typeof(LuaNil).GetField(nameof(LuaNil.Nil), BindingFlags.Static | BindingFlags.Public)); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Ldc_I4_M1); gen.Emit(OpCodes.Ldloc, methodArgs); gen.Emit(OpCodes.Callvirt, typeof(ILuaValue).GetMethod(nameof(ILuaValue.Invoke))); gen.Emit(OpCodes.Stloc, ret); // Store any by-ref parameters in the arguments for (int i = 0; i < args.Length; i++) { if (args[i].IsOut) { // arg_{i+1} = methodArgs[{i}].As<T>(); gen.Emit(OpCodes.Ldloc, methodArgs); gen.Emit(OpCodes.Ldc_I4, i); gen.Emit(OpCodes.Callvirt, typeof(ILuaMultiValue).GetMethod("get_Item")); gen.Emit(OpCodes.Callvirt, typeof(ILuaValue).GetMethod(nameof(ILuaValue.As)) .MakeGenericMethod(args[i].ParameterType)); gen.Emit(OpCodes.Starg, i + 1); } } // return ret.As<{info.Return}>(); if (delegateMethod.ReturnType != null && delegateMethod.ReturnType != typeof(void)) { gen.Emit(OpCodes.Ldloc, ret); gen.Emit(OpCodes.Callvirt, typeof(ILuaValue).GetMethod(nameof(ILuaValue.As)) .MakeGenericMethod(delegateMethod.ReturnType)); } gen.Emit(OpCodes.Ret); //// public <>_type_(ILuaEnvironment E, ILuaValue method) ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(ILuaEnvironment), typeof(ILuaValue) }); gen = cb.GetILGenerator(); // base(); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Call, typeof(object).GetConstructor(new Type[0])); // this.E = E; gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldarg_1); gen.Emit(OpCodes.Stfld, E); // this.meth = method; gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldarg_2); gen.Emit(OpCodes.Stfld, meth); gen.Emit(OpCodes.Ret); return(tb.CreateType()); }