Question

J'ai plusieurs méthodes spéciales, et je veux analyser dans l'assemblage qu'ils appelle compilé.

Exemple:

public static class SrcHelper {
    [MySpecialMethod]
    [Conditional( "DEBUG" )]
    public static void ToDo( params object[] info ) {
        /* do nothing */
        /* this method is not called when code is compiled in RELEASE mode */
    }
}
// ... somewhere else in another assembly ...
Array CreateArraySampleMethod( int size ) {
    // This call has only informative character. No functionality is required.
    SrcHelper.ToDo( "Should create array of ", typeof( MyClass ), " with specified size." );
    throw new NotImplementedException();
}

A partir de ce code compilé je veux obtenir les valeurs de l'argument { « devrait créer une matrice de » MyClass « avec la taille spécifiée. » }. J'ai essayé utiliser Cecil de Mono, et j'ai trouvé les instructions pour l'appel méthode « ToDo ». Mais maintenant, je suis confus comment identifier l'instruction avec des valeurs d'argument.

Je sais, il peut y avoir des situations complexes et ne peuvent être résolus de la valeur de certains arguments. Mais je dois résoudre que des valeurs constantes -. Il est suffisant pour mon but

Merci.

EDIT: La méthode "ToDo" (et similaires) devraient être utilisés comme alternative aux commentaires (//, / * ... * /), et après la compilation, doivent être analysées IL et de la documentation et autogenerated todo-list pour le montage en béton.

Était-ce utile?

La solution

La génération de code est un peu déroutant, mais peut être fait pour les cas simples:

compilation:

public static void Main(string[] args)
{
    Console.WriteLine("", // ignore this argument
       "Should create array of ", typeof(int), " with specified size." "x");
}

(ajout de "x" pour le forcer à utiliser une surcharge params)

donne

.method public hidebysig static void Main(string[] args) cil managed
{
    .custom instance void [mscorlib]System.STAThreadAttribute::.ctor()
    .maxstack 4
    .locals init (
        [0] object[] objArray)
    L_0000: ldstr ""
    L_0005: ldc.i4.4 
    L_0006: newarr object
    L_000b: stloc.0 
    L_000c: ldloc.0 
    L_000d: ldc.i4.0 
    L_000e: ldstr "Should create array of "
    L_0013: stelem.ref 
    L_0014: ldloc.0 
    L_0015: ldc.i4.1 
    L_0016: ldtoken int32
    L_001b: call class [mscorlib]System.Type 
                [mscorlib]System.Type::GetTypeFromHandle(
                    valuetype [mscorlib]System.RuntimeTypeHandle)
    L_0020: stelem.ref 
    L_0021: ldloc.0 
    L_0022: ldc.i4.2 
    L_0023: ldstr " with specified size."
    L_0028: stelem.ref 
    L_0029: ldloc.0 
    L_002a: ldc.i4.3 
    L_002b: ldstr "x"
    L_0030: stelem.ref 
    L_0031: ldloc.0 
    L_0032: call void [mscorlib]System.Console::WriteLine(string, object[])
    L_0037: ret 
}

Vous avez à faire est d'analyser le il pour détecter les arguments poussés dans le tableau généré par le compilateur. un heristic qui est fragile mais peut-être suffisant pour dire:

  1. trouver appel à ma méthode.
  2. trouver le plus proche objet newarr précédent
  3. prendre toutes ldstr et ldtoken entre ceux-ci et supposer qu'ils sont les arguments.

Ceci est rude, mais peut être suffisant pour vos besoins.

Une approche de style AOP vous obtiendrez ce que vous voulez à runtime en instrumentant simplement chaque appel à vider les valeurs, mais au moment sompile l'approche ci-dessus est votre seule option réaliste, étant donné que l'IL.

Le code généré peut être très différent dans les versions Release, il vous sera impossible de repérer l'auto tableau généré vers quelqu'un qu'il créant explicitement eux-mêmes (qui peut être plus loin du site d'appel ou même dans une autre méthode / constructeur / classe .

Proviso

Je note après avoir modifié la raison pour laquelle vous voulez faire l'attribut annotations sont à base d'une solution, je mieux ne vois pas pourquoi vous voulez faire dans la méthode lorsque vous pouvez attribuer directement ...

Autres conseils

Je ne suis pas sûr de ce que vous voulez dire. Cependant, notez que votre fonction vraiment ne reçoit que un Argument: un tableau. C'est ce que vous obtenez dans IL, aussi. l'intérieur la fonction, vous pouvez marcher à travers le réseau pour obtenir ses valeurs:

public static void ToDo( params object[] info ) {
    foreach (object x in info)
        Console.WriteLine(x);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top