.NET, Architecture, ALM, Cloud
Petit tutorial très pratique qui va nous permettre de récupérer le Code IL de nos méthodes dynamiques et donc de nos expressions lambda compilé à la volée.
Prenons un exemple simple :
Expression<Func<int, int>> methodE = a => a * 2;
var method = methodE.Compile();
int result = method(4);
On va donc récupérer le code IL généré du corps de notre méthode "a * 2" qui a donc un paramètre a de type Integer et qui retourne un Integer.
Avant de voire en détail comment procéder, comment nous allons nous y prendre ? : A l'aide de l'extension de débogage SOS de Microsoft, nous allons récupérer l'adresse de notre Func puis de notre méthode dynamique pour ensuite récupérer le code IL de celle-ci.
Tout d'abord, activer le debug du code non managé dans votre projet (Fenêtre VS de Propriété de votre projet, onglet "Debug" puis cochez "Enable unmanaged code debugging"). Lancez votre application en positionnant un point d'arrêt une fois que votre expression a été compilé, puis à partir de la fenêtre de Debug Visual Studio "Immediate Window", lancez les commande suivante (et servez vous des résultats de chaque commande pour adapter la suivante) :
.load sos
!dso
PDB symbol for clr.dll not loaded
OS Thread Id: 0x1730 (5936)
ESP/REG Object Name
...
002EF00C 02562b94 System.Func`2[[System.Int32, mscorlib],[System.Int32, mscorlib]]
...
!do 02562b94
Name: System.Func`2[[System.Int32, mscorlib],[System.Int32, mscorlib]]
MethodTable: 00182820
EEClass: 0018004c
Size: 32(0x20) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
6b6ef5e8 4000074 4 System.Object 0 instance 02562afc _target
6b6ef5e8 4000075 8 System.Object 0 instance 0255e4a4 _methodBase
6b6eaa2c 4000076 c System.IntPtr 1 instance 003C00B0 _methodPtr
6b6eaa2c 4000077 10 System.IntPtr 1 instance 00000000 _methodPtrAux
6b6ef5e8 4000078 14 System.Object 0 instance bf8c6aa000000000 _invocationList
6b6eaa2c 4000079 18 System.IntPtr 1 instance 00000000 _invocationCount
!do 0255e4a4
Name: System.Reflection.Emit.DynamicMethod+RTDynamicMethod
MethodTable: 6b6af24c
EEClass: 6b3fc920
Size: 28(0x1c) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
6b6f1938 4002932 4 ...mit.DynamicMethod 0 instance 0255d188 m_owner
6b6a6c28 4002933 8 System.Object[] 0 instance bfb0786800000000 m_parameters
6b6ef9ac 4002934 c System.String 0 instance 0255d024 m_name
6b6ab7bc 4002935 10 System.Int32 1 instance 22 m_attributes
6b6ab608 4002936 14 System.Int32 1 instance 1 m_callingConvention
!dumpil 0255d188
This is dynamic IL. Exception info is not reported at this time.
If a token is unresolved, run "!do <addr>" on the addr given
in parenthesis. You can also look at the token table yourself, by
running "!DumpArray 0255e890".
IL_0000: ldarg.1
IL_0001: ldc.i4.2
IL_0002: mul
IL_0003: ret
Nous chargeons SOS via la commande ".load sos", ensuite nous récupérons l'adresse de nos objets via "!dso" (dso pour dumpstackobjects). On récupère l'adresse de notre Func pour ensuite récupérer l'adresse de sa méthode via la commande "do" (pour dumpobject) en précisant son adresse, et en récupère enfin l'adresse de notre méthode dynamique toujours à l'aide de "do".
Il nous suffit alors d'utiliser la commande "dumpil" en précisant l'adresse de la méthode pour récupérer son code IL.