1. 程式人生 > >WPF 判斷呼叫方法堆疊

WPF 判斷呼叫方法堆疊

原文: WPF 判斷呼叫方法堆疊

最近遇到一個問題,經常有小夥伴在類A的構造裡呼叫靜態函式B,但是這時B依賴於A的初始化完成,於是就無限迴圈。所以我需要在判斷小夥伴呼叫B時是否在A的構造方法裡,如果是就給他異常。

本文告訴大家如何使用 StackTrace 獲得呼叫堆疊,並且判斷當前是否構造呼叫

假設有方法 Foo ,如果需要判斷 Foo 的呼叫有哪些,可以使用下面的程式碼

        public void Foo()
        {
            var stackTrace = new StackTrace();
        }

使用var n = stackTrace.FrameCount;可以得到當前的棧有幾個,最頂部就是最近呼叫。

例如呼叫是 lindexi->A->csdn->Foo 那麼對應的棧就是下表

序號 方法
3 lindexi
2 A
1 csdn
0 Foo

如果要判斷當前的呼叫是建構函式,那麼需要知道,建構函式就是.ctor 那麼使用下面的程式碼就可以判斷

            var stackTrace = new StackTrace();
            var n = stackTrace.FrameCount;
            for (int i = 0; i < n; i++)
            {
                //判斷構造
                var cto = ".ctor";
                var f = stackTrace.GetFrame(i).GetMethod();
                if (f.Name.Equals
(cto)) { Console.WriteLine("構造使用"); } Console.WriteLine(stackTrace.GetFrame(i).GetMethod().Name); }

建議把上面的程式碼複製到一個專案,自己跑一下就知道了

如果還需要判斷是指定型別的建構函式,那麼需要使用下面的程式碼,下面程式碼判斷是型別GqpluGkmoanvp的構造呼叫

        public void Foo()
        {
            var stackTrace = new StackTrace();
            var n = stackTrace.FrameCount;
            for (int i = 0; i < n; i++)
            {
                //判斷構造
                var cto = ".ctor";
                var f = stackTrace.GetFrame(i).GetMethod();
                if (f.Name.Equals(cto))
                {
                    var t = f.DeclaringType;
                    if (t.IsSubclassOf(typeof(GqpluGkmoanvp)) || t == typeof(GqpluGkmoanvp))
                    {
                        Console.WriteLine("構造使用");
                    }
                }
                Console.WriteLine(stackTrace.GetFrame(i).GetMethod().Name);
            }
        }
    }

實際使用t.IsSubclassOf(typeof(GqpluGkmoanvp))有些多餘,但是寫了也可以。因為如果寫在構造,那麼就會先呼叫基類的構造方法,所以已經會出現判斷到基類的構造方法。

例如有下面的類,在構造方法呼叫Foo,那麼呼叫堆疊就是 Foo-A1-A

public class A1:A
{
    public A1()
    {
        Foo();
    }
}

public class A
{

}

下面是我封裝的一個方法,用於判斷當前呼叫是否在某個類裡的某個方法

         /// <summary>
        /// 檢視呼叫這個方式是否在某個類的某個方法
        /// </summary>
        /// <param name="class"></param>
        /// <param name="method"></param>
        /// <returns></returns>
        public static bool CheckStackClassMethod(Type @class, string method)
        {
            var stackTrace = new StackTrace();
            var n = stackTrace.FrameCount;
            for (int i = 1; i < n; i++)
            {
                var f = stackTrace.GetFrame(i).GetMethod();
                if (f.Name.Equals(method))
                {
                    var t = f.DeclaringType;
                    if (t == @class || t.IsSubclassOf(@class) || (@class.IsInterface && @class.IsAssignableFrom(t)))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

程式碼放在WPF 判斷呼叫方法堆疊

因為傳入的型別可能是介面,所以型別判斷就需要加上介面繼承的,所有程式碼已經給了大家。

使用這個方法,可以把判斷是否在某個類的某個方法呼叫這個函式就可以修改為下面程式碼

       public void Foo()
        {
            if (CheckStackClassMethod(typeof(GqpluGkmoanvp), ".d"))
            {
                Console.WriteLine("構造使用");
            }
        }

我經過測試下使用這個函式,判斷是否我要保護的方法在我不想要被呼叫的類呼叫,如果是就丟擲異常。接著我的朋友的程式碼跑不過,就把我祭天。

感謝 walterlv

知識共享許可協議
本作品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名林德熙(包含連結:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可釋出。如有任何疑問,請與我聯絡