Cómo hacer OpCodes. ¿Llamar correctamente?

Estoy practicando. DynamicMethod desde este post, y todo funcionó bien con los siguientes códigos:

    private delegate long squareDel(int a);
    squareDel test;

    private void Form1_Load(object sender, EventArgs e)
    {
        DynamicMethod dm = new DynamicMethod("", typeof(long), new Type[] { typeof(int) },typeof(Form1));
        ILGenerator ig = dm.GetILGenerator();

        ig.Emit(OpCodes.Ldarg_0);
        ig.Emit(OpCodes.Conv_I8);
        ig.Emit(OpCodes.Dup);
        ig.Emit(OpCodes.Mul);
        ig.Emit(OpCodes.Ret);

        test = (squareDel)dm.CreateDelegate(typeof(squareDel));
`  `}

    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show(test(int.Parse(textBox1.Text)).ToString());
    }

Pero ahora estoy tratando de incorporarlo con OpCodes. Llame con un pequeño método:

    public long Test(int s)
    {
        return s*s;
    }

y hacer el siguiente cambio al código:

        MethodInfo mi = typeof(Form1).GetMethod("Test",new Type[] { typeof(int) });

        ig.Emit(OpCodes.Ldarg_0);
        ig.EmitCall(OpCodes.Call, mi,null);
        ig.Emit(OpCodes.Dup);
        ig.Emit(OpCodes.Mul);
        ig.Emit(OpCodes.Ret);

Y ahora me tira System.InvalidProgramException.

Fui a buscar la excepción en línea e intenté cambiar mis propiedades de construcción de este post para nada.

Y no puedo encontrar las llamadas "Configuraciones Avanzadas" de este post, así que supongo que este post está fuera de la fecha (es de hace 5 años después de todo).

Entonces, ¿alguien podría ser tan amable y enseñarme cómo arreglarlo?

¡Mucho apreciado!

Pregunta hecha hace 3 años, 4 meses, 28 días - Por quantumquasar


2 Respuestas:

  • El error que estás viendo se debe a cómo estás intentando llamar al método estático Test dentro de tu código utilizando OpCodes.

    Para llamar un método estático utilizando OpCodes, debes usar la instrucción call en lugar de callvirt, ya que callvirt se utiliza para llamar a métodos de instancia. Además, necesitas asegurarte de que estás pasando correctamente los parámetros requeridos por el método en el orden correcto.

    Aquí te dejo la corrección en tu código para llamar al método estático Test correctamente utilizando OpCodes:

    csharp
    private void Form1_Load(object sender, EventArgs e)
    {
        DynamicMethod dm = new DynamicMethod("", typeof(long), new Type[] { typeof(int) }, typeof(Form1));
        ILGenerator ig = dm.GetILGenerator();
    
        ig.Emit(OpCodes.Ldarg_0);
    
        // Llamando al método estático Test
        MethodInfo mi = typeof(Form1).GetMethod("Test", new Type[] { typeof(int) });
        ig.Emit(OpCodes.Call, mi);
    
        ig.Emit(OpCodes.Dup);
        ig.Emit(OpCodes.Mul);
        ig.Emit(OpCodes.Ret);
    
        test = (squareDel)dm.CreateDelegate(typeof(squareDel));
    }
    

    Al realizar esta modificación en tu código, deberías ser capaz de llamar correctamente al método estático Test utilizando OpCodes sin recibir la excepción System.InvalidProgramException.

    Respondida el Dec 20, 2020 a las 15:17 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El error System.InvalidProgramException se produce cuando el CLR detecta un programa inválido. En este caso, el error se debe a que estás intentando emitir una llamada a un método que no existe en el tipo actual.

    Para corregir el error, debes asegurarte de que el método Test exista en la clase Form1. Si el método existe en otra clase, debes emitir una llamada al método utilizando el opcode Callvirt en lugar de Call.

    Aquí tienes el código corregido:

    
    MethodInfo mi = typeof(Form1).GetMethod("Test", new Type[] { typeof(int) });
    
    ig.Emit(OpCodes.Ldarg_0);
    ig.EmitCall(OpCodes.Callvirt, mi, null);
    ig.Emit(OpCodes.Dup);
    ig.Emit(OpCodes.Mul);
    ig.Emit(OpCodes.Ret);
    

    Respondida el Dec 20, 2020 a las 15:22 - por Gemini

    Votos positivos: 0 | Votos negativos: 0