如何判断哪个方法调用了相同的事件?

本文介绍了一种在C#中利用StackTrace类确定事件触发源头的方法。通过实例演示了如何通过StackTrace和StackFrame类来获取调用堆栈信息,进而判断是哪个方法调用了事件绑定的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨日MSDN有人询问我一个问题,假设某个类中有两个事件定义(它们的委托完全一致,并且同时绑定到一个方法)。假设C#代码如下:

namespace CSharp
{
    class A
    {
        public event Action MyEvent;
        public event Action MyEvent2;

        public void Call()
        {
            MyEvent();
        }
        public void Call2()
        {
            MyEvent2();
        }
    }

    class Program
    {

        static void Main(string[] args)
        {
            A a = new A();
            a.MyEvent += a_MyEvent;
            a.MyEvent2 += a_MyEvent;
            a.Call();
            a.Call2();
        }


        static void a_MyEvent()
        {
            //如何知道是Call还是Call2在调用此事件绑定方法呢?
        }

    }
}

我没有想到用StackTrance类就可以!

查阅MSDN,并且通过一些简单的示例代码我得知这个类就是提供断点调试时候“Trace”列表自动跟踪作用的。因此代码可以这样写:

 static void a_MyEvent()
        {
            StackTrace st = new StackTrace();
            Console.WriteLine(st.GetFrames()[1].GetMethod().Name);
        }

StackTrace是一个跟踪状态类,跟踪当前方法是何种方法,以及调用该方法的上层方法,上上层方法。那么我们可以想:Main调用了Call,而Call又调用了这个事件绑定方法。因此一次调用跟踪这个trace就会产生“Main","Call"和"a_MyEvent"(两次调用,总共产生6次)——由于是”栈“,因此存放顺序是"a_MyEvent"最上,“Main"最下。这些个跟踪的方法存于StackFrames属性中(每一个StackFrame也是一个类,表示一个“跟踪帧”),作为集合出现。其标号分别是0,1,2……即当前(声明StackTrace那一刻开始跟踪的方法为0,上级方法1,再上级为2……以此类推)。因此此处为1。

要证明这点也不难,可以完全打印:

namespace CSharp
{
    class A
    {
        public event Action MyEvent;
        public event Action MyEvent2;

        public void Call(int i)
        {
            MyEvent();
        }
        public void Call2()
        {
            MyEvent2();
        }
    }

    class Program
    {

        static void Main(string[] args)
        {
            A a = new A();
            a.MyEvent += a_MyEvent;
            a.MyEvent2 += a_MyEvent;
            a.Call(1);
            a.Call2();
        }


        static void a_MyEvent()
        {
            StackTrace st = new StackTrace();
            foreach (var item in st.GetFrames())
            {
                Console.WriteLine(item.GetMethod().Name);
            }
        }

    }
}

你也可以用StackFrame(单个帧)去跟踪当前方法,譬如:

 static void a_MyEvent()
        {
            StackFrame sf = new StackFrame();
            Console.WriteLine(sf.GetMethod().Name);
        }

此时输出的是a_MyEvent,如果你需要跟踪其父类(上级),那么你可以在构造函数中写入数字(表示从当前的帧数往上追溯其第N个父类方法)。本题是追溯其第一个父类,自然写1:

 static void a_MyEvent()
        {
            StackFrame sf = new StackFrame(1);
            Console.WriteLine(sf.GetMethod().Name);
        }

所以总结如下:

StackTrace包含一个完整跟踪的StackFrame列表,通过StackTrace寻找帧数直接可以通过索引(0,1,2)。其中0表示当前方法(定义StackTrace开始跟踪的那一个方法),1表示其父类方法……以此类推。

StackFrame仅包含当前开始跟踪的那个方法(=MethodBase.GetCurrentMethod().Name),因此如果要寻找其父类,必须在构造函数中填入某个数字(表示要寻找其第N个父类方法)。

转载于:https://www.cnblogs.com/ServiceboyNew/archive/2013/02/28/2936671.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值