這個題目也可以更改成「如何在某類別中的方法裡,主動知道是哪個類別的哪個方法來調用你?」,總而言之就是如何知道是誰來呼叫我?在傳統的應用下通常都是子類別去調用父類別的某些方法,所以子類別早就知道目的父類別是誰了。而在某些特定的應用場合下,我們可能需要知道是誰來調用,動態的去輸出或決策某些路徑或程序,這時候這篇文章就派上用場了。
答案就是堆疊:System.Diagnostics.StackTrace
一開始有這個需求的時候,我也是找遍網路想破頭就是不得其門而路,但心中很確定一定某道門可以進入。後來使用Stack關鍵字去尋找果然找出端倪,進而達成我要的目的,話不多說先來看程式碼:
首先定義一個父類別,然後在「WhoWakeMeUp()」(誰調用我?)的方法中實作System.Diagnostics.StackTrace。
class Father { public Father() { WriteLine("我是Father建構子。"); WhoWakeMeUp(); } public virtual string Name() { WhoWakeMeUp(); return "王爸爸"; } private void WhoWakeMeUp() { //取得調用堆疊 System.Diagnostics.StackTrace oStack = new System.Diagnostics.StackTrace(true); //取得呼叫當前方法之上一層類別方法(因為程式碼已經寫在「父類別的方法」裡面了,所以要跳2層) System.Reflection.MethodBase oMethod = oStack.GetFrame(2).GetMethod(); //取得呼叫當前方法之上一層類別方法的類別名稱 WriteLine($"我知道是{oMethod.DeclaringType.Name}類別的{oMethod.Name}方法來調用我。"); } }
子類別純粹繼承父類別,用來觸發父類別的建構子,並且在覆寫父類別的方法中,試圖去調用父類別的Name方法,故意在觸發一次WhoWakeMeUp()。
class Child : Father { public Child() { WriteLine("我是Child建構子。"); } public override string Name() { return $"王小明 / {base.Name()}"; } }
在Main方法裡面,分別進行Child、Father以及第三方類別Program的三種測試,都可以看到「到底是誰在呼叫(調用)我」這段程式碼工作的很正常。
class Program { public static void Main() { //測試:以子類別繼承父類別的方式調用 Child oTemp1 = new Child(); WriteLine(oTemp1.Name()); WriteLine("-----"); //測試:以直接呼叫父類別的方式調用 Father oTemp2 = new Father(); WriteLine(oTemp2.Name()); WriteLine("-----"); //測試:以外部類別的方式調用父類別 Program oTemp3 = new Program(); oTemp3.Test(); Read(); } private Father _Father; public Program() { _Father = new Father(); } public void Test() { WriteLine(_Father.Name()); } }
//測試:以子類別繼承父類別的方式調用 我是Father建構子。 我知道是Child類別的.ctor方法來調用我。 我是Child建構子。 我知道是Child類別的Name方法來調用我。 王小明 / 王爸爸 ----- //測試:以直接呼叫父類別的方式調用 我是Father建構子。 我知道是Program類別的Main方法來調用我。 我知道是Program類別的Main方法來調用我。 王爸爸 ----- //測試:以外部類別的方式調用父類別 我是Father建構子。 我知道是Program類別的.ctor方法來調用我。 我知道是Program類別的Test方法來調用我。 王爸爸C# Debug WhoCallMe WhoRunMe FatherClass SuperClass ChildClass SubClass 誰在調用我 誰在呼叫我 誰在Call我