internal void EndSet(Type stackType)
 {
     BuildUtil.Convert(_il, stackType, typeof(T), false);
     _il.Emit(OpCodes.Stelem_Ref);
 }
        private MethodBuilder AddMethodImpl(MethodInfo mi)
        {
            ParameterInfo[] parameters = mi.GetParameters();
            Type[]          paramTypes = ParamTypes(parameters, false);

            MethodBuilder mdb = _tb.DefineMethod(mi.Name, MethodAttributes.Public | MethodAttributes.Virtual, mi.ReturnType, paramTypes);

            if (mi.ContainsGenericParameters)
            {
                Type[]   ts = mi.GetGenericArguments();
                string[] ss = new string[ts.Length];
                for (int i = 0; i < ts.Length; i++)
                {
                    ss[i] = ts[i].Name;
                }
                GenericTypeParameterBuilder[] genericParameters = mdb.DefineGenericParameters(ss);
                for (int i = 0; i < genericParameters.Length; i++)
                {
                    genericParameters[i].SetGenericParameterAttributes(ts[i].GetTypeInfo().GenericParameterAttributes);
                }
            }
            ILGenerator il = mdb.GetILGenerator();

            ParametersArray args = new ParametersArray(il, paramTypes);

            // object[] args = new object[paramCount];
            il.Emit(OpCodes.Nop);
            GenericArray <object> argsArr = new GenericArray <object>(il, ParamTypes(parameters, true).Length);

            for (int i = 0; i < parameters.Length; i++)
            {
                // args[i] = argi;
                if (!parameters[i].IsOut)
                {
                    argsArr.BeginSet(i);
                    args.Get(i);
                    argsArr.EndSet(parameters[i].ParameterType);
                }
            }

            // object[] packed = new object[PackedArgs.PackedTypes.Length];
            GenericArray <object> packedArr = new GenericArray <object>(il, PackedArgs.PackedTypes.Length);

            // packed[PackedArgs.DispatchProxyPosition] = this;
            packedArr.BeginSet(GlobalConst.DISPATCH_PROXY_POSITION);
            il.Emit(OpCodes.Ldarg_0);
            packedArr.EndSet(typeof(DispatchProxyAsync));

            // packed[PackedArgs.DeclaringTypePosition] = typeof(iface);
            MethodInfo Type_GetTypeFromHandle = typeof(Type).GetRuntimeMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) });
            int        methodToken;
            Type       declaringType;

            _assembly.GetTokenForMethod(mi, out declaringType, out methodToken);
            packedArr.BeginSet(GlobalConst.DECLARING_TYPE_POSITION);
            il.Emit(OpCodes.Ldtoken, declaringType);
            il.Emit(OpCodes.Call, Type_GetTypeFromHandle);
            packedArr.EndSet(typeof(object));

            // packed[PackedArgs.MethodTokenPosition] = iface method token;
            packedArr.BeginSet(GlobalConst.METHOD_TOKEN_POSITION);
            il.Emit(OpCodes.Ldc_I4, methodToken);
            packedArr.EndSet(typeof(Int32));

            // packed[PackedArgs.ArgsPosition] = args;
            packedArr.BeginSet(GlobalConst.ARGS_POSITION);
            argsArr.Load();
            packedArr.EndSet(typeof(object[]));

            // packed[PackedArgs.GenericTypesPosition] = mi.GetGenericArguments();
            if (mi.ContainsGenericParameters)
            {
                packedArr.BeginSet(GlobalConst.GENERIC_TYPES_POSITION);
                Type[] genericTypes         = mi.GetGenericArguments();
                GenericArray <Type> typeArr = new GenericArray <Type>(il, genericTypes.Length);
                for (int i = 0; i < genericTypes.Length; ++i)
                {
                    typeArr.BeginSet(i);
                    il.Emit(OpCodes.Ldtoken, genericTypes[i]);
                    il.Emit(OpCodes.Call, Type_GetTypeFromHandle);
                    typeArr.EndSet(typeof(Type));
                }
                typeArr.Load();
                packedArr.EndSet(typeof(Type[]));
            }

            for (int i = 0; i < parameters.Length; i++)
            {
                if (parameters[i].ParameterType.IsByRef)
                {
                    args.BeginSet(i);
                    argsArr.Get(i);
                    args.EndSet(i, typeof(object));
                }
            }

            MethodInfo invokeMethod = s_delegateInvoke;

            if (mi.ReturnType == typeof(Task))
            {
                invokeMethod = s_delegateInvokeAsync;
            }
            if (IsGenericTask(mi.ReturnType))
            {
                var returnTypes = mi.ReturnType.GetGenericArguments();
                invokeMethod = s_delegateinvokeAsyncT.MakeGenericMethod(returnTypes);
            }

            // Call AsyncDispatchProxyGenerator.Invoke(object[]), InvokeAsync or InvokeAsyncT
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, _fields[GlobalConst.InvokeActionFieldAndCtorParameterIndex]);
            packedArr.Load();
            il.Emit(OpCodes.Callvirt, invokeMethod);
            if (mi.ReturnType != typeof(void))
            {
                BuildUtil.Convert(il, typeof(object), mi.ReturnType, false);
            }
            else
            {
                il.Emit(OpCodes.Pop);
            }

            il.Emit(OpCodes.Ret);

            _tb.DefineMethodOverride(mdb, mi);
            return(mdb);
        }