Pergunta

Eu tenho vários métodos especiais, e eu quero analisar se chama em compilado montagem.

Exemplo:

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 deste código compilado Quero obter os valores de argumento { "deverá criar variedade de" MyClass "com o tamanho especificado." }. Tentei uso Cecil de Mono, e eu achei as instruções para a chamada de método "todo". Mas agora estou confuso como identificar instrução com valores de argumento.

Eu sei, pode haver situação complexa, e o valor de algum argumento não pode ser resolvido. Mas eu preciso resolver apenas valores constantes. - É o suficiente para o meu propósito

Graças.

EDIT: O método de "todo" (e similares) deve ser usado como alternativa para comentários (//, / * ... * /), e após a compilação, deve ser IL analisado e gerado automaticamente documentação e Todo-lista para betão de montagem.

Foi útil?

Solução

A geração de código é um pouco confuso, mas pode ser feito para casos simples:

compilação:

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

(adicionando "x" para forçá-lo a usar uma sobrecarga params)

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

Assim que você tem a fazer é analisar o il para detectar os argumentos sendo empurrado para a matriz de compilador gerado. um heristic que é frágil, mas pode ser suficiente dizer:

  1. encontrar chamada para 'meu método'.
  2. encontrar mais próximo objeto newarr anterior
  3. tomar todas ldstr e ldtoken entre estes e assumir que eles são os argumentos.

Esta é duro, mas pode ser suficiente para suas necessidades.

abordagem de estilo Um AOP vai te dar o que você quer em tempo de execução , simplesmente instrumentação cada chamada para despejar os valores, mas no momento sompile a abordagem acima é a sua única opção realista, dada somente a IL.

O código gerado pode ser muito diferente nas compilações, Você não será capaz de detectar a auto série gerado versos alguém criá-lo explicitamente si (que pode ser mais longe do site de chamada ou até mesmo em um diferente método / construtor / aula .

cláusula

Devo observar após a sua edição por que você quer fazer isso esse atributo com base anotações são uma solução muito melhor, não vejo por que você iria querer fazer isso no método quando você pode atribuí-lo diretamente ...

Outras dicas

Eu não tenho certeza que você quer dizer. No entanto, aviso que a sua função realmente só fica um argumento: um array. Isso é o que você recebe em IL, também. Dentro a função, você pode percorrer a matriz para obter seus valores:

public static void ToDo( params object[] info ) {
    foreach (object x in info)
        Console.WriteLine(x);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top