Я пытаюсь изучить Reflection.Emit, погрузившись прямо в него, и на данный момент я застрял в следующем:
У меня есть этот метод PInvoke
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);
Когда я доберусь до этой части, я воспроизведу из ILDASM реальную программу C#, из которой это исходит:
ilgen.Emit(OpCodes.Call, typeBuilder.GetMethod("CryptEnumOIDInfo"));
Я получаю сообщение об ошибке «Вызванный элемент не поддерживается до создания типа».
Для некоторой ясности, не вставляя всю программу, у меня есть свой класс в TypeBuilder, который просто представляет класс Program по умолчанию, в котором нет ничего, кроме PInvoke и Main() (из исходной программы, которую я испускаю). ILGenerator основан на MethodBuilder, представляющем упомянутый Main().
То, что я пробовал до сих пор, находится в конце ilgen OpCodes, которые я вызываю (где выдается эта ошибка, и после нее есть еще несколько OpCodes, но я еще не там, очевидно):
Type myType = typeBuilder.CreateType()
Однако я не захожу так далеко, потому что ошибка, по сути, говорит о том, что мне нужно создать тип раньше
Я также пытался создать MethodInfo для метода PInvoke и вместо этого передать его в код операции Call, но я получил ту же ошибку (и также был сбит с толку тем, как создать объект MethodInfo для PInvokeMethod), что я и сделал:
MethodInfo miPinvoke = typeBuilder.GetMethod("CryptEnumOIDInfo");
Наконец, в конце концов, я переместил typeBuilder.CreateType() до запуска ilgen, но затем он жалуется на то, что метод, конечно, не имеет тела.
Любая помощь очень ценится. С удовольствием опубликую дополнительную информацию, если это необходимо для ясности.
MethodBuilder
происходит от MethodInfo
, используйте объект mbCryptEnumOIDInfo
, который у вас уже есть в IlGenerator
. Этот шаблон используется для большинства ...Builder
и соответствующих ...Info
классов в Reflection.Emit.
Звонок должен быть:
ilgen.Emit(OpCodes.Call, mbCryptEnumOIDInfo);
Спасибо, что исправили это, и не могу поверить, что я пропустил это. Ценить это!