zoukankan      html  css  js  c++  java
  • 如何判断哪个方法调用了相同的事件?

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

  • 相关阅读:
    设计模式 23
    生活杂谈
    设计模式经典书籍
    ABP 样板开发框架系列
    关键字
    vs 2015
    优秀文章推荐
    Parallel 并行编程
    CSRF
    sql性能优化
  • 原文地址:https://www.cnblogs.com/ServiceboyNew/p/2936671.html
Copyright © 2011-2022 走看看