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

昨日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/p/2936671.html