2011-07-23 19 views
5

Quiero generar IL para una aplicación multiproceso. Como el primer paso escribí una aplicación simple e inspeccioné, generé IL utilizando ILSpy.Generando IL para métodos anónimos

public class ThreadTesting 
{ 
    public static void Main() 
    { 
     Thread thread = new Thread(() => Print("Hello from t!")); 
     thread.Start(); 
    } 

    public static void Print(string message) 
    { 
     Console.WriteLine(message); 
    } 
} 
.method public hidebysig static 
    void Main() cil managed 
{ 
    // Method begins at RVA 0x2060 
    // Code size 46 (0x2e) 
    .maxstack 3 
    .entrypoint 
    .locals init (
     [0] class [mscorlib]System.Threading.Thread 
    ) 

    IL_0000: nop 
    IL_0001: ldsfld class [mscorlib]System.Threading.ThreadStart ThreadTesting::'CS$<>9__CachedAnonymousMethodDelegate1' 
    IL_0006: brtrue.s IL_001b 

    IL_0008: ldnull 
    IL_0009: ldftn void ThreadTesting::'<Main>b__0'() 
    IL_000f: newobj instance void [mscorlib]System.Threading.ThreadStart::.ctor(object, native int) 
    IL_0014: stsfld class [mscorlib]System.Threading.ThreadStart ThreadTesting::'CS$<>9__CachedAnonymousMethodDelegate1' 
    IL_0019: br.s IL_001b 

    IL_001b: ldsfld class [mscorlib]System.Threading.ThreadStart ThreadTesting::'CS$<>9__CachedAnonymousMethodDelegate1' 
    IL_0020: newobj instance void [mscorlib]System.Threading.Thread::.ctor(class [mscorlib]System.Threading.ThreadStart) 
    IL_0025: stloc.0 
    IL_0026: ldloc.0 
    IL_0027: callvirt instance void [mscorlib]System.Threading.Thread::Start() 
    IL_002c: nop 
    IL_002d: ret 
} // end of method ThreadTesting::Main 

I fue capaz de generar más de los anteriores códigos de IL utilizando System.Reflection.Emit espacio de nombres.

Desafortunado No pude averiguar cómo generar siguiendo el código IL utilizando System.Reflection.Emit.

IL_0001: ldsfld class [mscorlib]System.Threading.ThreadStart ThreadTesting::'CS$<>9__CachedAnonymousMethodDelegate1' 

Así puede alguien ayudarme a averiguar cómo generar IL para los métodos anónimos?

Respuesta

6

Esa IL es simplemente la forma en que el compilador guarda en caché la instancia de delegado; no es parte del método en sí. Si está utilizando DynamicMethod (que probablemente debería), simplemente llame a CreateDelegate ({su tipo de delegado}), transfiéralo al tipo de delegado deseado (probablemente ThreadStart) y almacene la instancia delegada (tipada) en cualquier lugar.

4

El no es un concepto como "método anónimo" en IL. Lo que hace el compilador de C# es crear un método normal con un nombre indescriptible (<Main>b__0) y un campo estático para almacenar en caché a un delegado en el método (CS$<>9__CachedAnonymousMethodDelegate1).

Lo que debe hacer depende de lo que desea hacer. Si no desea almacenar en caché al delegado, no tiene que hacerlo, puede crearlo y simplificará un poco su código.

Si convierte el método anónimo en método normal y lo ve en ILSpy, verá el IL simplificado (sin ldsfld) y podrá generarlo.

+0

El almacenamiento en caché es quizás aún más importante que el uso de emit - pero si nunca va a ser reutilizado no hay razón para almacenarlo. –

+0

@Marc, suponía que tanto el método anónimo como el método que lo utiliza se generan con emitir. En ese caso, creo que el almacenamiento en caché no ayuda mucho, ya que guarda solo una llamada al constructor delegado. Si el almacenamiento en caché no significa generar todo el método nuevamente, entonces, por supuesto, tienes razón. – svick

Cuestiones relacionadas