Search code examples
c#.netreflection.emit

"The invoked member is not supported before the type is created" in Reflection.Emit


I'm trying to learn Reflection.Emit by diving right in and what I'm stumped on at the moment is the following:

I have this PInvoke method

Type[] ptCryptEnumOIDInfo = { typeof(UInt32), typeof(UInt32), typeof(IntPtr), typeof(IntPtr) };
            MethodBuilder mbCryptEnumOIDInfo = typeBuilder.DefinePInvokeMethod(
                "CryptEnumOIDInfo",
                "crypt32.dll",
                MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.PinvokeImpl,
                CallingConventions.Standard,
                typeof(bool),
                ptCryptEnumOIDInfo,
                System.Runtime.InteropServices.CallingConvention.Winapi,
                System.Runtime.InteropServices.CharSet.Ansi);
            mbCryptEnumOIDInfo.SetImplementationFlags(mbCryptEnumOIDInfo.GetMethodImplementationFlags() | MethodImplAttributes.PreserveSig);

When I get to this part I'm replicating from ILDASM of the actual C# program that this comes from:

ilgen.Emit(OpCodes.Call, typeBuilder.GetMethod("CryptEnumOIDInfo"));

I get the error "The invoked member is not supported before the type is created".

For some clarity without pasting in the entire program, I have my class in TypeBuilder that is just representing the default Program class which has nothing in it other than the PInvoke and Main() (from the original program I'm emitting). The ILGenerator is based on the MethodBuilder representing said Main()

What I've tried so far is at the end of the ilgen OpCodes I'm calling (where this error is being thrown and there's a few more OpCodes after it but I'm not there yet obviously) is:

Type myType = typeBuilder.CreateType()

However I don't get that far because the error is essentially saying I need to create the type earlier

I also had tried making a MethodInfo for the PInvoke method and passing that into the Call opcode instead but I was getting the same error (and also was confused on how to make a MethodInfo object for a PInvokeMethod) which I did by:

MethodInfo miPinvoke = typeBuilder.GetMethod("CryptEnumOIDInfo");

Finally, just on a long shot I moved the typeBuilder.CreateType() before the ilgen starts but then it complains about the method not have a body of course.

Any and all help is very much appreciated. Happy to post more information if needed for clarity.


Solution

  • MethodBuilder is derived from MethodInfo, use the mbCryptEnumOIDInfo object you already have in the IlGenerator. This pattern is used for the most ...Builder and corresponding ...Info classes in Reflection.Emit.

    The call should be:

    ilgen.Emit(OpCodes.Call, mbCryptEnumOIDInfo);