ILGenerator::EmitCall Method (OpCode, MethodInfo^, array<Type^>^)
Puts a call or callvirt instruction onto the Microsoft intermediate language (MSIL) stream to call a varargs method.
Assembly: mscorlib (in mscorlib.dll)
public: virtual void EmitCall( OpCode opcode, MethodInfo^ methodInfo, array<Type^>^ optionalParameterTypes )
Parameters
- opcode
-
Type:
System.Reflection.Emit::OpCode
The MSIL instruction to be emitted onto the stream. Must be OpCodes::Call, OpCodes::Callvirt, or OpCodes::Newobj.
- methodInfo
-
Type:
System.Reflection::MethodInfo^
The varargs method to be called.
- optionalParameterTypes
-
Type:
array<System::Type^>^
The types of the optional arguments if the method is a varargs method; otherwise, null.
| Exception | Condition |
|---|---|
| ArgumentException | opcode does not specify a method call. |
| ArgumentNullException | methodInfo is null. |
| InvalidOperationException | The calling convention for the method is not varargs, but optional parameter types are supplied. This exception is thrown in the .NET Framework versions 1.0 and 1.1, In subsequent versions, no exception is thrown. |
The EmitCall method is used to emit calls to varargs methods because there is no overload of the Emit method that specifies the parameter types of the variable arguments.
To emit calls to methods that do not use the VarArgs calling convention, use the Emit(OpCode, MethodInfo^) method overload.
Beginning with the .NET Framework version 2.0, the EmitCall method does not throw an exception when optional parameter types are specified for a method that is not varargs. InvalidProgramException is thrown when the call is executed.
The following code example emits two methods, a varargs method and a method that calls the varargs method. The EmitCall method is used to emit the call to the varargs method.
using namespace System; using namespace System::Reflection; using namespace System::Reflection::Emit; void main() { String^ name = "InMemory"; AssemblyBuilder^ asmBldr = AppDomain::CurrentDomain->DefineDynamicAssembly(gcnew AssemblyName(name), AssemblyBuilderAccess::Run); ModuleBuilder^ modBldr = asmBldr->DefineDynamicModule(name); TypeBuilder^ tb = modBldr->DefineType("DemoVararg"); // Create a vararg method with no return value and one // string argument. (The string argument type is the only // element of an array of Type objects.) // MethodBuilder^ mb1 = tb->DefineMethod("VarargMethod", MethodAttributes::Public | MethodAttributes::Static, CallingConventions::VarArgs, nullptr, gcnew array<Type^> { String::typeid }); ILGenerator^ il1 = mb1->GetILGenerator(); LocalBuilder^ locAi = il1->DeclareLocal(ArgIterator::typeid); LocalBuilder^ locNext = il1->DeclareLocal(bool::typeid); Label labelCheckCondition = il1->DefineLabel(); Label labelNext = il1->DefineLabel(); // Load the fixed argument and print it. il1->Emit(OpCodes::Ldarg_0); il1->Emit(OpCodes::Call, Console::typeid->GetMethod("Write", gcnew array<Type^> { String::typeid })); // Load the address of the local variable represented by // locAi, which will hold the ArgIterator. il1->Emit(OpCodes::Ldloca_S, locAi); // Load the address of the argument list, and call the // ArgIterator constructor that takes an array of runtime // argument handles. il1->Emit(OpCodes::Arglist); il1->Emit(OpCodes::Call, ArgIterator::typeid->GetConstructor( gcnew array<Type^> { RuntimeArgumentHandle::typeid })); // Enter the loop at the point where the remaining argument // count is tested. il1->Emit(OpCodes::Br_S, labelCheckCondition); // At the top of the loop, call GetNextArg to get the next // argument from the ArgIterator. Convert the typed reference // to an object reference and write the object to the console. il1->MarkLabel(labelNext); il1->Emit(OpCodes::Ldloca_S, locAi); il1->Emit(OpCodes::Call, ArgIterator::typeid->GetMethod("GetNextArg", Type::EmptyTypes)); il1->Emit(OpCodes::Call, TypedReference::typeid->GetMethod("ToObject")); il1->Emit(OpCodes::Call, Console::typeid->GetMethod("Write", gcnew array<Type^> { Object::typeid })); il1->MarkLabel(labelCheckCondition); il1->Emit(OpCodes::Ldloca_S, locAi); il1->Emit(OpCodes::Call, ArgIterator::typeid->GetMethod("GetRemainingCount")); // If the remaining count is greater than zero, go to // the top of the loop. il1->Emit(OpCodes::Ldc_I4_0); il1->Emit(OpCodes::Cgt); il1->Emit(OpCodes::Stloc_1); il1->Emit(OpCodes::Ldloc_1); il1->Emit(OpCodes::Brtrue_S, labelNext); il1->Emit(OpCodes::Ret); // Create a method that contains a call to the vararg // method. MethodBuilder^ mb2 = tb->DefineMethod("CallVarargMethod", MethodAttributes::Public | MethodAttributes::Static, CallingConventions::Standard, nullptr, Type::EmptyTypes); ILGenerator^ il2 = mb2->GetILGenerator(); // Push arguments on the stack: one for the fixed string // parameter, and two for the list. il2->Emit(OpCodes::Ldstr, "Hello "); il2->Emit(OpCodes::Ldstr, "world "); il2->Emit(OpCodes::Ldc_I4, 2006); // Call the vararg method, specifying the types of the // arguments in the list. il2->EmitCall(OpCodes::Call, mb1, gcnew array<Type^> { String::typeid, int::typeid }); il2->Emit(OpCodes::Ret); Type^ type = tb->CreateType(); type->GetMethod("CallVarargMethod")->Invoke(nullptr, nullptr); } /* This code example produces the following output: Hello world 2006 */
Available since 1.1
Portable Class Library
Supported in: portable .NET platforms
Silverlight
Available since 2.0
Windows Phone Silverlight
Available since 7.1