Mono.Embedding.NativeDelegateServices.EmitWrapper C# (CSharp) Method

EmitWrapper() static private method

Emits a new NativeDelegate subclass for the specified delegateType. See also the comments at the bottom of the NativeDelegate class.
static private EmitWrapper ( Type delegateType ) : Type
delegateType System.Type
return System.Type
        static Type EmitWrapper(Type delegateType)
        {
            //
            // define class
            //
            // public class NativeDelegateWrapperXXX : NativeDelegateWrapper
            //
            TypeBuilder tb = moduleBuilder.DefineType(
                String.Format("NativeDelegateWrapper{0}", sequence++),
                TypeAttributes.Public,
                typeof (NativeDelegateWrapper)
                );

            MethodInfo method = delegateType.GetMethod("Invoke");
            ParameterInfo[] pi = method.GetParameters();
            var parameterTypes = new Type[pi.Length];

            // The icall's parameters are prefixed with an IntPtr "context" parameter.
            var icallParameterTypes = new Type[pi.Length + 1];
            icallParameterTypes[0] = typeof (IntPtr);

            for (int i = 0; i < pi.Length; i++)
            {
                parameterTypes[i] = pi[i].ParameterType;
                if (parameterTypes[i].IsByRef)
                    throw new NotSupportedException("ByRef parameters are not supported");
                icallParameterTypes[i + 1] = parameterTypes[i];
            }

            //
            // define ctor
            //
            // public .ctor(IntPtr context)
            //
            ConstructorBuilder cb = tb.DefineConstructor(
                MethodAttributes.Public | MethodAttributes.HideBySig,
                CallingConventions.Standard,
                new[] {typeof (IntPtr)}
                );

            ILGenerator gen = cb.GetILGenerator();

            //
            // call base.ctor(context, delegateType)
            //
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Ldtoken, delegateType);
            gen.Emit(OpCodes.Call, typeof (Type).GetMethod("GetTypeFromHandle"));
            gen.Emit(OpCodes.Call, NativeDelegateWrapper.CtorInfo);
            gen.Emit(OpCodes.Ret);

            //
            // define method
            //
            // [MethodImpl(MethodImplOptions.InternalCall)]
            // static extern <returni-type> NativeHandler(IntPtr context,
            //         <signature>)
            //
            MethodBuilder icallBuilder = tb.DefineMethod(
                "NativeHandler",
                MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig,
                CallingConventions.Standard,
                method.ReturnType,
                icallParameterTypes
                );

            icallBuilder.SetImplementationFlags(MethodImplAttributes.InternalCall);

            //
            // define method
            //
            // public <return-type> Invoke(<signature>)
            //
            MethodBuilder mb = tb.DefineMethod(
                "Invoke",
                MethodAttributes.Public | MethodAttributes.HideBySig,
                method.CallingConvention,
                method.ReturnType,
                parameterTypes
                );

            gen = mb.GetILGenerator();

            //
            // public <return-type> Invoke(<signature>)
            // {
            //     return NativeHandler(context, <signature>);
            // }
            //
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Ldfld, NativeDelegateWrapper.ContextFieldInfo);
            for (int i = 0; i < parameterTypes.Length; i++)
                gen.Emit(OpCodes.Ldarg, i + 1);
            gen.Emit(OpCodes.Call, icallBuilder);
            gen.Emit(OpCodes.Ret);

            return tb.CreateType();
        }
    }