NDepend : quelles sont les méthodes décorées de l’attribut DllImport qui sont appelées indirectement par mon code ?
Parmis les fonctionnalités de NDepend, il y en a une que j’apprécie particulièrement, c’est le CQL (Code Query Language).
Il permet souvent de répondre assez vite à certaines questions, comme sur les longueurs de noms, et aussi à celle-ci : quelles sont les méthodes décorées de l’attribut DllImport qui sont appelées indirectement par mon code (mais pas définies dans celui-ci) ?
Facile ! :-)
Exemple avec les assemblies Lucene.Net et Snowball.Net dans le rôle de “mon code” (mais je n’en suis pas du tout l’auteur) :
SELECT METHODS OUT OF ASSEMBLIES "Lucene.Net", "Snowball.Net" WHERE (IsUsedBy "ASSEMBLY:Lucene.Net" OR IsUsedBy "ASSEMBLY:Snowball.Net") AND HasAttribute "System.Runtime.InteropServices.DllImportAttribute" ORDER BY DepthOfIsUsedBy
Merci Patrick !
UPDATE :
Patrick vient de me faire une remarque intéressante au sujet de l’attribut DllImport : il n’a pas le même impact que les autres sur l’IL généré.
Au lieu de persister de la même manière que les autres attributs, il se traduit par un flag “PinvokeImpl” dans les métadonnées, et on retrouve l’information de la même manière sur la signature de la méthode.
Ainsi si on prend le code suivant :
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern Int32 MessageBox(
HandleRef hWnd,
String text,
String caption,
Int32 type
);
Nous aurons les informations suivantes :
Method #1 (06000003)
-------------------------------------------------------
MethodName: MessageBox (06000003)
Flags : [Public] [Static] [HideBySig] [ReuseSlot] [PinvokeImpl] (00002096)
RVA : 0x00000000
ImplFlags : [IL] [Managed] [PreserveSig] (00000080)
CallCnvntn: [DEFAULT]
ReturnType: I4
4 Arguments
…
Et cette signature :
.method public hidebysig static pinvokeimpl("user32.dll" autochar winapi)
int32 MessageBox(valuetype [mscorlib]System.Runtime.InteropServices.HandleRef hWnd,
string text,
string caption,
int32 'type') cil managed preservesig
{
}
Alors que sur ce code :
[MyAttribute("Blah")]
public Int32 MyMethod()
{
Int32 sum = 0;
checked
{
for (Int32 currentValue = 0; currentValue < 10; currentValue++)
{
sum += currentValue;
}
}
return sum;
}
Nous aurons ces informations :
Method #1 (06000001)
-------------------------------------------------------
MethodName: MyMethod (06000001)
Flags : [Public] [HideBySig] [ReuseSlot] (00000086)
RVA : 0x00002050
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: I4
No arguments.
CustomAttribute #1 (0c000001)
-------------------------------------------------------
CustomAttribute Type: 06000004
CustomAttributeName: DllImportTest.MyAttributeAttribute :: instance void .ctor(class System.String)
Length: 9
Value : 01 00 04 42 6c 61 68 00 00 > Blah <
ctor args: ("Blah")
Et cette signature :
.method public hidebysig instance int32 MyMethod() cil managed
{
.custom instance void DllImportTest.MyAttributeAttribute::.ctor(string) = {string('Blah')}
// Code size 21 (0x15)
.maxstack 2
.locals init ([0] int32 sum,
[1] int32 currentValue)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldc.i4.0
IL_0003: stloc.1
IL_0004: br.s IL_000e
IL_0006: ldloc.0
IL_0007: ldloc.1
IL_0008: add.ovf
IL_0009: stloc.0
IL_000a: ldloc.1
IL_000b: ldc.i4.1
IL_000c: add.ovf
IL_000d: stloc.1
IL_000e: ldloc.1
IL_000f: ldc.i4.s 10
IL_0011: blt.s IL_0006
IL_0013: ldloc.0
IL_0014: ret
} // end of method MyClass::MyMethod
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :