Pregunta

Tengo varios métodos especiales, y quiero que analizan las llamadas en el ensamblado compilado.

Ejemplo:

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 este código compilado quiero obtener los valores de los argumentos { "debería crear gran variedad de" MyClass "con el tamaño especificado." }. Probé el uso de Cecil Mono, y me encontré con las instrucciones para el método llamado "Tareas". Pero ahora estoy confundido cómo identificar la instrucción con valores de argumento.

Lo sé, no puede haber situación compleja, y el valor de un argumento no se puede resolver. Pero necesito resolver sólo valores constantes. - Es suficiente para mi propósito

Gracias.

EDIT: El método de "todo" (y otras similares) deben utilizarse como alternativa a los comentarios (//, / * ... * /), y después de la compilación, deben ser IL analizó y documentación autogenerada y todo-lista para el ensamblaje de hormigón.

¿Fue útil?

Solución

La generación de código es un poco confuso, pero se puede hacer para los casos simples:

compilación:

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

(añadiendo "x" para forzarlo a utilizar una sobrecarga params)

da

.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 
}

Así que hay que hacer es analizar el il para detectar los argumentos siendo empujados hacia la matriz generada compilador. un heristic que es frágil, pero podría ser suficiente con decir:

  1. encontrar a llamar 'mi método'.
  2. encuentre más próximo objeto newarr anterior
  3. tomar todo ldstr y ldtoken entre éstas y asumir que son los argumentos.

Este es peligrosa, pero puede ser suficiente para sus necesidades.

Un enfoque estilo AOP le conseguirá lo que desea en tiempo de ejecución simplemente la instrumentación de cada llamada para volcar los valores, pero en el momento sompile el enfoque anterior es la única opción realista teniendo en cuenta sólo el IL.

El código generado puede ser muy diferente en generaciones de lanzamiento, usted no será capaz de detectar el automóvil genera gama versos alguien crear explícitamente ellos mismos (que puede estar más lejos del sitio de llamada o incluso en un método / constructor / clase diferente .

Proviso

Debo hacer notar después de su edición por la cual quiere hacer esto que las anotaciones basadas atributo son una solución mucho mejor, no puedo ver por qué querría hacer esto en el método cuando se puede atribuir directamente ...

Otros consejos

No estoy seguro de lo que quiere decir. Sin embargo, se dio cuenta de que su función realmente sólo se pone un argumento: una matriz. Eso es lo que se obtiene de la IL, también. Dentro la función, se puede caminar a través de la matriz para obtener sus valores:

public static void ToDo( params object[] info ) {
    foreach (object x in info)
        Console.WriteLine(x);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top