2012-10-12 14 views
5

Mam następujący kod C#:funkcja Emitting z opcjonalnym parametrem

public static double f(double x1, double x2 = 1) 
{ 
    return x1 * x2; 
} 

I tu jest to kod IL (ILSpy):

.method public hidebysig static 
    float64 f (
     float64 x1, 
     [opt] float64 x2 
    ) cil managed 
{ 
    .param [2] = float64(1) 
    // Method begins at RVA 0x20c6 
    // Code size 4 (0x4) 
    .maxstack 8 

    IL_0000: ldarg.0 
    IL_0001: ldarg.1 
    IL_0002: mul 
    IL_0003: ret 
} // end of method A::f 

Jak mogę dostać go z System.Reflection.Emit lub lepiej z Mono.Cecil?

Odpowiedz

4

Jeśli chcę coś zrobić z Mono.Cecil, zwykle tworzę klasę/metodę w C# z oczekiwanym kodem. Następnie sprawdzam go (upewnij się, że używasz go w trybie Release) z Mono.Cecil i ponownie go stwórz.

Tak że trzeba MethodDefinition z parametrem name, attributes i returnType. Nazwa: „f”

Atrybuty metodę byłoby: Mono.Cecil.MethodAttributes.FamANDAssem | Mono.Cecil.MethodAttributes.Family | Mono.Cecil.MethodAttributes.Static | Mono.Cecil.MethodAttributes.HideBySig

oraz typ zwracanej (typu Mono.Cecil.TypeReference jako System.Double)

chodzi o parametry, istnieją dwa ParameterDefinition można dodatek z target.Parameters.Add()

Jeden z parametrów ma wartość domyślną, więc jego atrybuty muszą być Mono.Cecil.ParameterAttributes.Optional | Mono.Cecil.ParameterAttributes.HasDefault i jego Constant zestaw do 1.0 (w przypadku)

Teraz dla organizmu metoda:

target.Body.GetILProcessor(); // target is your `MethodDefinition` object. 

Po kontroli zgodnie z instrukcjami target.Body.Instructions, widzimy następujące kody:

IL_0000: ldarg.0 
IL_0001: ldarg.1 
IL_0002: mul 
IL_0003: stloc.0 
IL_0004: br.s IL_0007 
IL_0005: ldloc.0 
IL_0007: ret 

Więc po prostu dodać kody w odpowiedniej kolejności

processor.Append(OpCodes.Ldarg_0); 

Po tym, wstrzyknąć/zapisać MethodDefinition do odpowiedniego zespołu.

Mój zespół inspektor kod wygląda mniej więcej tak:

private static void EnumerateAssembly(AssemblyDefinition assembly) 
     { 
      foreach (var module in assembly.Modules) 
      { 
       foreach (var type in module.GetAllTypes()) 
       { 
        foreach (var field in type.Fields) 
        { 
         Debug.Print(field.ToString()); 
        } 
        foreach (var method in type.Methods) 
        { 
         Debug.Print(method.ToString()); 
         foreach (var instruction in method.Body.Instructions) 
         { 
          Debug.Print(instruction.ToString()); 
         } 
        } 
       } 
      } 
     } 
+5

nigdy nie powinno trzeba dodać „nop”. Jeśli widzisz "nop", oznacza to (niezmiennie), że wbudowałeś tryb debugowania zamiast trybu zwalniania, zanim spojrzysz na kod w reflektorze/isdasm/cokolwiek innego. Byłoby znacznie lepiej sprawdzić IL z wersji release. –

+0

@MarcGravell Dziękujemy za opinie! – Alex

+0

Nie wiedziałem tylko o ustawieniu wartości stałej na wartość. Mimo wszystko dziekuję! –

Powiązane problemy