2009-03-05 20 views
46

可能性の重複:
How can I find the method that called the current method?メソッド内から呼び出し元のメソッド名を取得

私はオブジェクト内の多くの場所から呼び出されたオブジェクトのメソッドを持っています。この人気のあるメソッドを呼び出すメソッドの名前を取得するためのすばやく簡単な方法はありますか?私は...私が見てみたいと思い、それがMainから呼び出された場合Mainの値を見たい「ButtonClickPopularMethod()ButtonClickから呼び出された場合PopularMethod()以内

public Main() 
{ 
    PopularMethod(); 
} 

public ButtonClick(object sender, EventArgs e) 
{ 
    PopularMethod(); 
} 

public Button2Click(object sender, EventArgs e) 
{ 
    PopularMethod(); 
} 

public void PopularMethod() 
{ 
    //Get calling method name 
} 

擬似コードの例

私はSystem.Reflection.MethodBase.GetCurrentMethod()を見ていましたが、それは私に呼び出し方法を得ることはありません。私はStackTraceクラスを見てきましたが、メソッドが呼び出されるたびにスタックトレース全体を実行することは本当に喜ばしくありませんでした。

答えて

67

を私はそれがスタックをトレースすることなく行うことができるとは思いません。しかし、それはそれを行うにはかなり簡単です:

StackTrace stackTrace = new StackTrace(); 
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod(); 
Console.WriteLine(methodBase.Name); // e.g. 

しかし、私はあなたが本当にこれが必要な場合は、自分自身を停止し、依頼する必要がありだと思います。

+0

詳細については、 http://discuss.joelonsoftware.com/default.asp?dotnet.12.511358.10 –

+3

System.DiagnosticsはStackTraceの名前空間です。System.ReflectionはMethodBaseの名前空間です。 – Guvante

+0

Jason - ありがとう、 "StackTrace"メソッドがどのようにリソースを集中的に使用しているのかよく分かりませんが、これは私が探しているものを取得します。これは私のためのデバッグコードブロックに過ぎません。これは生産には向かないでしょう。あなたの助けをもう一度ありがとう! –

16

これは実際にはとても簡単です。

public void PopularMethod() 
{ 
    var currentMethod = System.Reflection.MethodInfo 
     .GetCurrentMethod(); // as MethodBase 
} 

しかしを通して注意してください、私はこの方法をインライン化すると、任意の効果を持っている場合に少し懐疑的です。これを行うと、JITコンパイラが途中で邪魔にならないようにすることができます。

[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 
public void PopularMethod() 
{ 
    var currentMethod = System.Reflection.MethodInfo 
     .GetCurrentMethod(); 
} 

呼び出し元のメソッドを取得するには、次の

[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 
public void PopularMethod() 
{ 
    // 1 == skip frames, false = no file info 
    var callingMethod = new System.Diagnostics.StackTrace(1, false) 
     .GetFrame(0).GetMethod(); 
} 
+3

John Leidgren - それは私に "PopularMethod"という名前を付けますが、私はPopularMethodと呼ばれるメソッドの名前が必要です。 –

+1

さて、スタックトレースは必要なものです。私はあなたの質問を誤解しました。 –

+0

代わりに.GetFrame(1)を代わりに使用します。 –

5

だけIMOパラメータに

public void PopularMethod(object sender) 
{ 

} 

を渡す:それはイベントには十分だ場合、それは、このために十分でなければなりません。

+0

Sruly - はい、間違いなくオプションですが、私はメソッド呼び出しを変更せずにそれを実行しようとしていました。これは私の最後の手段です。 –

+0

これをパブリックAPIとして公開していない限り、このようにすれば面倒なことはなく、リフレクションを使用するのはなぜですか? REEMember KISS – Sruly

+0

これは最高の答えです。リフレクションやその他のものを使用せず、パラメータを使用して発信者を識別します。 –

0

StackTraceクラスを使用し、次のフレームでStackFrame.GetMethod()を使用する必要があると思います。

しかしこれはReflectionを使用すると奇妙なようです。 PopularMethodを定義している場合、実際に必要な情報を渡すためのパラメータなどを定義することはできません。 (または基本クラスなどに入れてください)

1

Stackをトレースしてその方法を見つけ出すことができますが、私はあなたのデザインを考え直すよう促します。あなたのメソッドが何らかの「状態」について知っている必要がある場合は、単に列挙型などを作成して、これをパラメータとしてあなたのPopularMethod()に渡します。それらの線に沿って何か。あなたが投稿しているものに基づいて、スタックを追跡することは、IMOを過度に攻撃することになります。

4

私はしばしば自分自身がこれをやりたいと思っていましたが、私のシステムのデザインをリファクタリングするように終わってしまったので、私はこの "犬をかわす"というパターンを反パターンにしません。結果は常により堅牢なアーキテクチャでした。 .NET 4.5/C#5で

+0

これは答えですか? –

104

、これは単純です:

public void PopularMethod([CallerMemberName] string caller = null) 
{ 
    // look at caller 
} 

コンパイラが自動的に発信者の名前を追加します。 so:

void Foo() { 
    PopularMethod(); 
} 

"Foo"になります。

+0

優れたソリューション!私たちが4.5に変換するまで待つことはできません(それはしばらく時間がかかるでしょう)が、私は間違いなくこのことを念頭に置いています!ありがとうございました! –

+1

このソリューションのパフォーマンス結果はどのようなものですか? – Feckmore

+3

@Feckmore none whatsoever:コンパイラはコンパイル時にそれをリテラルとして追加します。 StackTraceなどを見ているようなものよりも、はるかに速いでしょう。基本的には、PopularMethod( "CurrentMethodName")としてコンパイルされます。 –

関連する問題