2009-08-18 12 views
5

¿Cómo puedo definir un DynamicMethod para un delegado que tenga un parámetro out, así?DynamicMethod y parámetros de salida?

public delegate void TestDelegate(out Action a); 

Digamos simplemente quiero un método que establece el argumento a a null cuando llamo el método.

Tenga en cuenta que sé que una forma probablemente mejor de manejar esto sería hacer que el método devuelva el delegado Action, pero esto es solo una parte simplificada de un proyecto más grande, y el método en cuestión ya devuelve un valor, I necesita manejar el parámetro out además de eso, de ahí la pregunta.

yo probamos este:

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

namespace ConsoleApplication8 
{ 
    public class Program 
    { 
     public delegate void TestDelegate(out Action a); 

     static void Main(String[] args) 
     { 
      var method = new DynamicMethod("TestMethod", typeof(void), 
       new Type[] { typeof(Action).MakeByRefType() }); 
      var il = method.GetILGenerator(); 

      // a = null; 
      il.Emit(OpCodes.Ldnull); 
      il.Emit(OpCodes.Starg, 0); 

      // return 
      il.Emit(OpCodes.Ret); 

      var del = (TestDelegate)method.CreateDelegate(typeof(TestDelegate)); 
      Action a; 
      del(out a); 
     } 
    } 
} 

Sin embargo, me sale esto:

VerificationException was unhandled: 
Operation could destabilize the runtime. 

en la línea del(out a);.

Tenga en cuenta que si hago un comentario de las dos líneas que cargan un valor nulo en la pila e intentan almacenarlo en el argumento, el método se ejecuta sin excepciones.


Editar: ¿Es este el mejor enfoque?

il.Emit(OpCodes.Ldarg_0); 
il.Emit(OpCodes.Ldnull); 
il.Emit(OpCodes.Stind_Ref); 
+0

¿Realmente se necesita crear un método dinámico? ¿por qué no simplemente implementar el método en una clase que se puede configurar para hacer lo que quieras en el tiempo de ejecución? –

+0

Realmente tiene que ser un método dinámico, este es un esfuerzo de optimización de último momento para lograr que un árbol de llamadas basado en la reflexión se ejecute más rápido. Hasta el momento, la sobrecarga de usar el método dinámico en comparación con el código existente parece ser aproximadamente un 85% menor, y este es el código que se llamará miles de veces por segundo. Las mediciones muestran que una gran cantidad de CPU está atada en el código de reflexión existente. –

Respuesta

6

Un out argumento es sólo un argumento ref con el OutAttribute aplicado al parámetro.

Para almacenar el argumento de ref, debe usar el código de operación stind, porque el argumento en sí es un puntero administrado a la ubicación real del objeto.

ldarg.0 
ldnull 
stind.ref 
Cuestiones relacionadas