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

2018-8-10-WPF-判断调用方法堆栈的更多相关文章

  1. WPF 判断调用方法堆栈

    原文:WPF 判断调用方法堆栈 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee.io 访问博客 ...

  2. XML序列化 判断是否是手机 字符操作普通帮助类 验证数据帮助类 IO帮助类 c# Lambda操作类封装 C# -- 使用反射(Reflect)获取dll文件中的类型并调用方法 C# -- 文件的压缩与解压(GZipStream)

    XML序列化   #region 序列化 /// <summary> /// XML序列化 /// </summary> /// <param name="ob ...

  3. 基于java.util.logging实现轻量级日志记录库(增加根据当前类class初始化,修复线程池模型(javaEE)下的堆栈轨迹顺序与当前调用方法不一致问题)

    前言: 本章介绍自己写的基于java.util.logging的轻量级日志记录库(baseLog). 该版本的日志记录库犹如其名,baseLog,是个实现日志记录基本功能的小库,适合小型项目使用,方便 ...

  4. .netcore 堆栈调用方法小记

    背景 上午临近午饭时,公司同事反馈验证码被攻击灌水.我们匆忙查询验证码明细,对已频繁出现的IP插入黑名单,但IP仍然隔断时间频繁变动,不得已之下只能先封禁对应公司id的验证码发送功能.年初时候,专门对 ...

  5. C#获取当前堆栈的各调用方法列表

    在使用.NET编写的代码在debug时很容易进行排查和定位问题,一旦项目上线并出现问题的话那么只能依靠系统日志来进行问题排查和定位,但当项目复杂时,即各种方法间相互调用将导致要获取具体的出错方法或调用 ...

  6. Delphi按名字调用方法高级解决方案

    转帖于https://lfzhs.iteye.com/blog/980200 按名字调用方法似乎一直以来都是大家比较关注的技术,在论坛上有一个经典的答复: type TProcedure = proc ...

  7. WPF 判断一个对象是否是设计时的窗口类型,而不是运行时的窗口

    原文:WPF 判断一个对象是否是设计时的窗口类型,而不是运行时的窗口 当我们对 Window 类型写一个附加属性的时候,在属性变更通知中我们需要判断依赖对象是否是一个窗口.但是,如果直接判断是否是 W ...

  8. phpcms 的实用相关接口,函数,调用方法

    常用函数 , 打开include/global.func.php,下面存放一些公共函数view plaincopy to clipboardprint? strip_tags() 调用内容过滤html ...

  9. phpcms常用接口调用方法

    常用函数 , 打开include/global.func.php,下面存放一些公共函数 view plaincopy to clipboardprint?function str_charset($i ...

随机推荐

  1. FastAdmin 使用 phpmail 出现 spl_autoload_register 错误

    FastAdmin 使用 phpmail 出现 spl_autoload_register 错误 现象 意思是 __autoload() 已经废弃 问题来源于:https://ask.fastadmi ...

  2. 部署 LAMP (CentOS 7.2)

    摘自:https://help.aliyun.com/document_detail/50774.html 简介 LAMP指Linux+Apache+Mysql/MariaDB+Perl/PHP/Py ...

  3. PHP是解释型语言:边解析边运行

    计算机语言的发展史: 第一代:机器语言,全部都是01010二进制代码,计算机能够直接的识别,运行效率是最高的,但是难编,难记,难区分,可移植性差! 第二代:汇编语言,其实就是符号化的机器语言,增加了编 ...

  4. Sublime Text3 安装less

    1.安装Sublime 插件 (1)安装LESS插件:因为Sublime不支持Less语法高亮,所以,先安装这个插件,方法: ctrl+shift+p>install Package>输入 ...

  5. node.js(二)各种模块

    我们知道Node.js适合于IO密集型应用,不适合于CPU密集型应用.    JS和Node.js区别:         JS运行于客户端浏览器中,存在兼容性问题:数据类型:值类型+引用类型(ES+D ...

  6. git安装方法

    点击 http://git-scm.com/download 选择你使用的操作系统,如果是linux就可以看到命令行,windows则是下载客户端

  7. 【OI】位运算操作

    一.基础操作 1.a<<b 将二进制a左移b位,不够的地方用0补位 例如 100<<2 == 10000 2.a>>b 将二进制a右移b位 例如 100>&g ...

  8. js中的replace问题和textarea回车符问题

    在textarea中输入回车符 在js读取textarea中的值有\r\n然后到业务层转换到string中就有可能变成空格形式然后被存入数据库,当在取出此值的时候则会变成空格的形式,因此我们需要将不显 ...

  9. Directx11教程(19) 画一个简单的地形

    原文:Directx11教程(19) 画一个简单的地形       通常我们在xz平面定义一个二维的网格,然后y的值根据一定的函数计算得到,比如正弦.余弦函数的组合等等,可以得到一个看似不错的地形或者 ...

  10. 使用curl指令实现restful接口操作

    curl 是很方便的Rest客戶端,可以很方便的完成許多Rest API測試的需求,甚至,如果是需要先登入或認證的rest api,也可以進行測試,利用curl指令,可以送出HTTP GET, POS ...