2009-08-18 10 views
5

Come definire un DynamicMethod per un delegato con un parametro simile a out, come questo?DynamicMethod e parametri esterni?

public delegate void TestDelegate(out Action a); 

Diciamo che voglio semplicemente un metodo che imposta l'argomento a a null quando chiamo il metodo.

Nota che un modo probabilmente migliore per gestirlo sarebbe quello di rendere il metodo restituito al delegato Action, ma questa è solo una parte semplificata di un progetto più grande, e il metodo in questione restituisce già un valore, I è necessario gestire il parametro out in aggiunta ad esso, quindi la domanda.

ho provato questo:

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); 
     } 
    } 
} 

Tuttavia, ottengo questo:

VerificationException was unhandled: 
Operation could destabilize the runtime. 

sulla linea del(out a);.

Si noti che se commento le due righe che caricano un null nello stack e tenta di memorizzarlo nell'argomento, il metodo viene eseguito senza eccezioni.


Edit: È questo l'approccio migliore?

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

È davvero necessario creare un metodo dinamico? perché non implementare semplicemente il metodo in una classe che può essere configurata per fare ciò che vuoi in fase di runtime? –

+0

Deve essere davvero un metodo dinamico, questo è uno sforzo di ottimizzazione last-stop per ottenere un enorme albero delle chiamate basato sulla riflessione da eseguire più velocemente. Finora il sovraccarico dell'utilizzo dell'approccio metodo dinamico contro il codice esistente sembra essere circa dell'85% in meno, e questo è il codice che verrà chiamato migliaia di volte al secondo. Le misurazioni mostrano che un bel po 'di CPU è legata al codice di riflessione esistente. –

risposta

6

Un argomento out è solo un argomento ref con il OutAttribute applicata al parametro.

Per archiviare l'argomento by-ref, è necessario utilizzare l'opcode stind, poiché l'argomento stesso è un puntatore gestito alla posizione effettiva dell'oggetto.

ldarg.0 
ldnull 
stind.ref 
Problemi correlati