代码之家  ›  专栏  ›  技术社区  ›  Tim

如何用c语言打印程序的执行流程#

  •  0
  • Tim  · 技术社区  · 6 年前

    我试图理解如何打印程序的执行流程。 我写了一些简单的代码来说明我的困境。

    我想把这个打印出来,比如: 在A班。 在B班,方法B。 在C班,方法C。

    StackTrace似乎给了我很多难以阅读的信息。有没有一种更简单的方法,或者一种更容易阅读的StackTrace?实际的代码要大得多,我不想在每个方法中都使用print语句,所以我认为这样做可能会使调试更容易。此外,我不能在实际代码中使用Visual Studio的调试器。所以,如果你们能建议我使用哪种功能,如果不是StackTrace,这将为我打印必要的信息,我将不胜感激。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace StackTrace
    {
            public class A
            {
                public static void Main(string[] args)
                {
                    B newB = new B();
                    newB.methodB();
                    Console.WriteLine("StackTrace: {0}", Environment.StackTrace); //I'd like to get the entire execution flow printed here
                    Console.ReadKey(); //just for testing, don't worry about this.
                }
            }
    
            public class B
            {
    
                public void methodB()
                {
                    C newC = new C();
                    //Console.WriteLine("In class B, method B");
                    newC.methodC();
                }
            }
    
            public class C
            {
                public void methodC()
                {
                    //Console.WriteLine("In class C, method C");
                }
            }
    }
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   S.C.    6 年前

    使用免费版本的postsharp,你可以很容易地做到这一点。首先,创建一个可以标记到方法上的属性:

    [PSerializable]
    public class LogInvocationAttribute : MethodInterceptionAspect
    {
        public override void OnInvoke(MethodInterceptionArgs args)
        {
            // TODO: use your existing logging method here. simple example here for now.
            Console.WriteLine($"{args.Instance.GetType()}.{args.Method.Name}");             
    
            // pass the call through to the original receiver
            args.Proceed();
        }
    }
    

    之后,任何想要记录的方法都可以将此属性应用于以下对象:

    [LogInvocation]
    public void SomeMethod(int someArg)
    {
        // do stuff
    }
    

    有了付费版本的postsharp,你实际上可以在基类级别应用这样的东西,并让它自动应用于儿童(所以请参考) here )但是对于你想要做的事情,将属性应用到你的方法中是一个简单的方法来获得你想要的。

        2
  •  2
  •   Tim    6 年前

    所以,对于每个回复我最初帖子的人来说,你可能会对我到目前为止的想法感兴趣。也许你们,或者其他人,可以加入这个讨论,我们可以找到一个更持久的解决方案。 但是,这里是我最接近自动化的地方:

    1) 创建此函数/方法并将其添加到每个类:

    public void LogInfo(string className, string methodName)
    {
       string info = ("In class: " + className + " In method: " + methodName);
       Console.WriteLine(info);
    }
    

    2) 将此行粘贴到代码库的相关区域:

     StackTrace stackTrace = new StackTrace();
     LogInfo(MethodBase.GetCurrentMethod().DeclaringType.Name, stackTrace.GetFrame(0).GetMethod().Name);
    

    3) 另外,请看一下我修改的代码,注意我们需要添加以下两个用例:
    使用系统。诊断学; 使用系统。反射

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    
    using System.Diagnostics;
    using System.Reflection;
    
    namespace StackTraceTest
    {
            public class A
            {
                public static void Main(string[] args)
                {
                    StackTrace stackTrace = new StackTrace();
                    LogInfo(MethodBase.GetCurrentMethod().DeclaringType.Name, stackTrace.GetFrame(0).GetMethod().Name);
    
                    B newB = new B();
                    newB.methodB();
    
                    LogInfo(MethodBase.GetCurrentMethod().DeclaringType.Name, stackTrace.GetFrame(0).GetMethod().Name);
    
                    /*for (int i = 0; i < stackTrace.FrameCount;i++)
                    {
                        LogInfo(stackTrace.GetFrame(i).GetType().Name, stackTrace.GetFrame(i).GetMethod().Name);
                    }*/
    
                    Console.ReadLine();
                }
    
                public static void LogInfo(string className, string methodName)
                {
                    string info = ("In class: " +className +" In method: " +methodName);
                    Console.WriteLine(info);
                }
            }
    
            public class B
            {
    
                public void methodB()
                {
                    StackTrace stackTrace = new StackTrace();
                    LogInfo(MethodBase.GetCurrentMethod().DeclaringType.Name, stackTrace.GetFrame(0).GetMethod().Name);
    
                    C newC = new C();
                    newC.methodC();
                }
    
                public void LogInfo(string className, string methodName)
                {
                    string info = ("In class: " + className + " In method: " + methodName);
                    Console.WriteLine(info);
                }
            }
    
            public class C
            {
                public void methodC()
                {
                    StackTrace stackTrace = new StackTrace();
                    LogInfo(MethodBase.GetCurrentMethod().DeclaringType.Name, stackTrace.GetFrame(0).GetMethod().Name);
                    //Console.WriteLine("StackTrace: {0}", Environment.StackTrace);
                }
    
                public void LogInfo(string className, string methodName)
                {
                    string info = ("In class: " + className + " In method: " + methodName);
                    Console.WriteLine(info);
                }
            }
    }
    

    4) 现在输出为:

    In class: A In method: Main
    In class: B In method: methodB
    In class: C In method: methodC
    In class: A In method: Main
    

    5) 有几件事我想告诉大家:我以为注释掉的for循环是一个神奇的子弹,可以在一行中解决所有问题,但它给出了输出:

    In class: StackFrame In method: Main
    In class: StackFrame In method: _nExecuteAssembly
    In class: StackFrame In method: ExecuteAssembly
    In class: StackFrame In method: RunUsersAssembly
    In class: StackFrame In method: ThreadStart_Context
    In class: StackFrame In method: RunInternal
    In class: StackFrame In method: Run
    In class: StackFrame In method: Run
    In class: StackFrame In method: ThreadStart
    

    还要注意C类中注释掉的行: post执行(如果你没有给出完整的个人信息,那么它就没有给出完整的结果)。然而,这意味着我需要深入挖掘代码,找到最后调用的方法,并将这行代码添加到其中。

    6) 资料来源: How performant is StackFrame?

    How can I find the method that called the current method?

    C# getting its own class name

    请告诉我你们的想法。谢谢