[英]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的性能如何?
請讓我知道你們的想法。 謝謝。
使用免費版本的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.