2016-05-20 53 views
0

我試圖得到第一個方法名稱,發起了多個方法調用。如何在C#中的多個子方法中找到父方法名?

,比如我有以下,

static void Main(string[] args) 
    { 
     Test1(); 
    } 

    static void Test1() 
    { 
     Test2(); 
    } 
    static void Test2() 
    { 
     Console.WriteLine("Soemthing"); 
    } 

在Test2的方法,我需要知道的主要方法已經啓動了這一鏈條。 我嘗試使用StackTrace和Reflection如下。

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

stackTrace.getFrame(1)不是我所期望的。它會給我以前的方法是Test1。

我不想將getFrame值硬編碼爲以獲取Main方法。

有沒有辦法從任何子方法獲得父方法沒有硬編碼幀值?

+0

如果您想手動執行此操作,您可以右鍵單擊該方法,然後單擊Go To Deifnition或Peek Definition,繼續這樣做,直到找到所需的父級。但自動im不知道 – Brendon

+4

「初始方法」的標準是什麼?在單線程控制檯應用程序中,它始終是'Main',不需要確定它...在Web服務中,您可以通過IIS程序集爬取... –

+0

我這樣做只是爲了研究。但最終我們會使用MVC 6 WebAPi。@RenéVogt –

回答

2

這會做你想要什麼:

var stackTrace = new StackTrace(); 
string lastCSharpMethodName = null; 
for (int i = 0;; i++) 
{ 
    if (stackTrace.GetFrame(i).GetILOffset() == StackFrame.OFFSET_UNKNOWN) 
     break; 

    lastCSharpMethodName = stackTrace.GetFrame(i).GetMethod().Name; 
} 

Console.WriteLine(lastCSharpMethodName); 

如果你在VS調試器仔細觀察,你會看到,呼籲建立一個控制檯應用程序(作爲一個例子),第一種方法是本地mscorlib.dll!System.Threading.ThreadHelper.ThreadStart()這是在語言部分標記爲Unknown

enter image description here

以上代碼的作用是過濾出unknown,並返回第一個已知行(請參閱:https://msdn.microsoft.com/en-us/library/system.diagnostics.stackframe.getiloffset(v=vs.110).aspx)。

這是你的情況是Main()

+0

這給了我想要的答案。但我試圖找出一種方法來做到這一點沒有循環。 此外我想申請這個WebApi,看看會發生什麼。 謝謝。 –

+0

它也適用於WebApi。 :)現在要找出一種沒有循環的方法。 –

+0

很高興聽到它。不知道有沒有一種方法可以做到這一點沒有循環,但祝你好運。 – kha

0

我想你不是在尋找堆棧中的第一幀,而是最後一幀。 隨着FrameCount屬性,你可以寫這樣的事情:

StackTrace stackTrace = new StackTrace(); 
MethodBase methodBase = stackTrace.GetFrame(stackTrace .FrameCount - 1).GetMethod(); // Not sure about the "- 1" 
Console.WriteLine(methodBase.Name); 

但是,如果我記得很清楚,有一些與堆棧調用切堆棧的下一個電話。 (當你在堆棧上進行第二次調用時,你不應該看到以前的方法調用。)

但我不確定。

+0

是@ romain-aga它也給我「ThreadStart」 –

+0

您可以使用「 - 2」代替。但它只適用於這種情況。也許你將不得不瀏覽所有的堆棧,直到你到達ThreadStart或者結束,並保存前一個項目以找到你正在尋找的東西。 –

0

您可以使用此方法來確定您的調用堆棧的頂部(或更好的底部)方法的名稱:

private static string GetInitialCaller() 
{ 
    StackTrace trace = new StackTrace(); 
    StackFrame frame = trace.GetFrames()?.LastOrDefault(); 
    return frame?.GetMethod()?.Name; 
} 

測試它在一個控制檯應用程序一樣,

private static void TestIt() 
{ 
    string caller = GetInitialCaller(); 
    Console.WriteLine($"Initial caller: {caller}"); 
} 
private static void Main() 
{ 
    TestIt(); 
} 

輸出:

Initial caller: Main 
+0

經過測試。但它給了我「ThreadStart」 –

+0

它是主要的來電者,如果你達到一個等級,你應該找到主要的。但即使你嘗試我的方法,你也會遇到一些問題。就像我在我的回答中所說的那樣,堆棧可以根據你調用它的位置/時間來切割。 –

+0

順便說一句@RenéVogt,很好的使用4.6功能:) –

0

使用@kha的回答,這應該做的伎倆同出一環。

  List<StackFrame> list = new StackTrace().GetFrames().ToList(); 
      int index = list.FindIndex(p => p.GetILOffset() == StackFrame.OFFSET_UNKNOWN); 
      var methodName = list.Select(p => p.GetMethod().Name).ElementAt(index-1); 
相關問題