• 2018-8-10-WPF-判断调用方法堆栈


    title author date CreateTime categories
    WPF 判断调用方法堆栈
    lindexi
    2018-08-10 19:16:53 +0800
    2018-2-13 17:23:3 +0800
    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 判断调用方法堆栈

    <script src='https://gitee.com/lindexi/codes/qigv3dt12js9ywoakpbu631/widget_preview?title=CheckStackClassMethod'></script>

    因为传入的类型可能是接口,所以类型判断就需要加上接口继承的,所有代码已经给了大家。

    使用这个方法,可以把判断是否在某个类的某个方法调用这个函数就可以修改为下面代码

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

    我经过测试下使用这个函数,判断是否我要保护的方法在我不想要被调用的类调用,如果是就抛出异常。接着我的朋友的代码跑不过,就把我祭天。

    感谢 walterlv

  • 相关阅读:
    Java 中的悲观锁和乐观锁的实现
    乐观锁和悲观锁的区别
    理解RESTful架构
    修复Linux下curl等无法使用 Let's Encrypt 证书
    呕心沥血 AR VR 好资源分享
    linux服务器出现大量TIME_WAIT的解决方法
    Ubuntu系统 无法删除 redis-server
    Python Flask jsonify a Decimal Error
    微信小程序 订阅消息 对接详细记录
    FTP时显示500 Illegal PORT command的解决
  • 原文地址:https://www.cnblogs.com/lindexi/p/12086281.html
Copyright © 2020-2023  润新知