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

昨日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个父类方法)。

你可能感兴趣的:(方法调用)