2012-06-30 11 views
5

Ho notato che .NET 4.5 ha un nuovo attributo chiamato [CallerMemberNameAttribute] che, se collegato a un parametro di un metodo, fornirà il nome stringa del metodo che ha chiamato quel metodo (se questo ha senso).C# Ottieni metodo di chiamata senza traccia stack

Tuttavia, sfortunatamente (perché voglio fare qualcosa con XNA) sto solo cercando .NET 4.0.

Voglio essere in grado di fare qualcosa di simile:

void MethodA() { 
    MethodB(); 
} 

void MethodB() { 
    string callingMethodName = (...?); 
    Console.WriteLine(callingMethodName); 
} 

Dove la mia uscita sarebbe MethodA.

So che potrei fare questo tramite analisi dello stack, ma questo è a) inaffidabile e b) sloooow ... quindi mi chiedo se c'è un altro modo per raccogliere tali informazioni, tuttavia, che possono essere ...

Speravo in qualsiasi idea o conoscenza che qualcuno potesse avere sul problema. Grazie in anticipo :)

+3

Passare il nome del metodo di chiamata come stringa? – Oded

+2

@Oded Beh sì, chiaramente potrei chiamare MethodB ("MethodA") ma il punto è che sto provando a farlo dinamicamente, in modo che se cambio MethodA in MethodC non devo modificare anche quella chiamata. – Xenoprimate

+0

Non è riuscito a fare quel punto nella domanda. – Oded

risposta

13

Se si utilizza Visual Studio 2012 per compilarlo, è possibile scrivere il proprio CallerMemberNameAttribute e utilizzarlo allo stesso modo di .NET 4.5 anche se si sceglie ancora .NET 4.0 o 3.5. Il compilatore eseguirà comunque la sostituzione al momento della compilazione, anche prendendo di mira una versione precedente del framework.

Basta aggiungere il seguente al progetto farà il trucco:

namespace System.Runtime.CompilerServices 
{ 
    public sealed class CallerMemberNameAttribute : Attribute { } 
} 
+0

Sono solo un programmatore hobbista, mi dispiace se questa è una domanda stupida, ma c'è un modo per vedere la fonte di CallerMemberNameAttribute di Microsoft? Per copiarlo, intendo. – Xenoprimate

+2

In generale, sì, è possibile decompilare le librerie .NET utilizzando ILSpy. http://wiki.sharpdevelop.net/ILSpy.ashx Tuttavia, raramente gli attributi rendono qualcosa di interessante, dal momento che il bit interessante è più spesso in che modo viene utilizzato da un altro codice. Per esempio. da ciò che dice @ReedCopsey, la trasformazione viene eseguita in fase di compilazione dal compilatore, non dall'attributo stesso, e non è nemmeno necessario il runtime .NET 4.5, quindi probabilmente non vedrai codice interessante. –

+0

Ah, quindi il compilatore vede solo il nome "CallerMemberNameAttribute" e inserisce la propria logica?Se è così, posso semplicemente creare un attributo vuoto con quel nome e funzionerà? – Xenoprimate

0

Si potrebbe fornire il nome del chiamante come parametro al metodo chiamato. Non è proprio quello che stai chiedendo, ma funziona senza la necessità di accedere al stack frame:

[MethodImpl(MethodImplOptions.NoInlining)] 
void MethodA() 
{ 
    string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name; 
    MethodB(methodName); 
} 

void MethodB(string callingMethodName) 
{ 
    Console.WriteLine(callingMethodName); 
} 

Utilizzando MethodBase.GetCurrentMethod(), è possibile garantire che l'implementazione rimane refactoring di sicurezza - se il nome del metodo modifiche, i risultati sarebbero ancora corretti.

Non dimenticare di contrassegnare il metodo di chiamata con MethodImplOptions.NoInlining in modo da evitare l'inlining del metodo.

Problemi correlati