簡體   English   中英

如何在C#中打印程序的執行流程

[英]How to print the flow of execution of a program in c#

我試圖了解如何打印程序的執行流程。 我寫了一些簡單的代碼來證明我的困境。

我想要打印以下內容:在A類中,Main。 在類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");
            }
        }
}

因此,對於對我的原始主題做出回應的每個人,您可能會對到目前為止我的想法感興趣。 也許你們或其他人可以加入討論,我們可以找到一個更永久的解決方案。 但是,這是我最接近的自動化方法:

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)另外,請查看我的修改后的代碼,並注意我們需要添加這兩個用例:
使用System.Diagnostics; 使用System.Reflection;

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 loop將是可以解決所有問題的魔術子彈,但是它提供了輸出:

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類中的注釋行:如果取消注釋,它將為您提供正確的整個執行流程(不會發布結果,因為它包含個人信息)。 但是,這意味着我需要深入研究代碼,找到最后調用的方法,並將這行代碼添加到其中。

6)資料來源: StackFrame的性能如何?

如何找到調用當前方法的方法?

C#獲得自己的類名

請讓我知道你們的想法。 謝謝。

使用免費版本的postharp,您可以很容易地做到這一點。 首先,創建一個可以標記到方法上的屬性:

[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
}

使用付費版本的postharp,您實際上可以在基類級別上應用類似的東西,並將其也自動應用到子類(SO參考此處 ),但是對於您想要執行的操作,將屬性應用於方法是一種簡單的方法你想要什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM