ILGenerator.EmitCall(OpCode, MethodInfo, Type[]) Método

Definição

Coloca uma instrução call ou callvirt no fluxo do MSIL (Microsoft Intermediate Language) para chamar um método varargs.

public virtual void EmitCall (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo methodInfo, Type[]? optionalParameterTypes);
public abstract void EmitCall (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo methodInfo, Type[]? optionalParameterTypes);
public virtual void EmitCall (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo methodInfo, Type[] optionalParameterTypes);
public void EmitCall (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo methodInfo, Type[] optionalParameterTypes);

Parâmetros

opcode
OpCode

A instrução MSIL para ser emitida para o fluxo. Deve ser Call, Callvirt ou Newobj.

methodInfo
MethodInfo

O método varargs a ser chamado.

optionalParameterTypes
Type[]

Os tipos dos argumentos opcionais se o método for um método varargs, caso contrário, null.

Exceções

opcode não especifica uma chamada de método.

methodInfo é null.

A convenção de chamada para o método não é varargs, mas são fornecidos tipos de parâmetro opcionais. Essa exceção é lançada nas versões do .NET Framework 1.0 e 1.1. Em versões subsequentes, nenhuma exceção é lançada.

Exemplos

O exemplo de código a seguir emite dois métodos, um varargs método e um método que chama o varargs método . O EmitCall método é usado para emitir a chamada para o varargs método .

using System;
using System.Reflection;
using System.Reflection.Emit;

class Example
{
    static void Main()
    {
        string name = "InMemory";

        AssemblyBuilder asmBldr =
           AppDomain.CurrentDomain.DefineDynamicAssembly(new 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,
            null,
            new Type[] { typeof(string) });

        ILGenerator il1 = mb1.GetILGenerator();

        LocalBuilder locAi = il1.DeclareLocal(typeof(ArgIterator));
        LocalBuilder locNext = il1.DeclareLocal(typeof(bool));

        Label labelCheckCondition = il1.DefineLabel();
        Label labelNext = il1.DefineLabel();

        // Load the fixed argument and print it.
        il1.Emit(OpCodes.Ldarg_0);
        il1.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(string) }));

        // 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, typeof(ArgIterator).GetConstructor(new Type[] { typeof(RuntimeArgumentHandle) }));

        // 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, typeof(ArgIterator).GetMethod("GetNextArg", Type.EmptyTypes));
        il1.Emit(OpCodes.Call, typeof(TypedReference).GetMethod("ToObject"));
        il1.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(object) }));

        il1.MarkLabel(labelCheckCondition);
        il1.Emit(OpCodes.Ldloca_S, locAi);
        il1.Emit(OpCodes.Call, typeof(ArgIterator).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,
            typeof(void), 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, new Type[] { typeof(string), typeof(int) });

        il2.Emit(OpCodes.Ret);

        Type type = tb.CreateType();
        type.GetMethod("CallVarargMethod").Invoke(null, null);
    }
}

/* This code example produces the following output:

Hello world 2006
 */

Comentários

O EmitCall método é usado para emitir chamadas para varargs métodos porque não há sobrecarga do Emit método que especifica os tipos de parâmetro dos argumentos de variável.

Para emitir chamadas para métodos que não usam a VarArgs convenção de chamada, use a sobrecarga do Emit(OpCode, MethodInfo) método .

O EmitCall método não gera uma exceção quando tipos de parâmetro opcionais são especificados para um método que não varargsé . InvalidProgramException é gerado quando a chamada é executada.

Aplica-se a

Produto Versões
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0 (package-provided), 2.1