Как напечатать поток выполнения программы в c # - PullRequest
0 голосов
/ 18 мая 2018

Я пытаюсь понять, как я могу напечатать поток выполнения программы.Я написал простой код, чтобы продемонстрировать мою дилемму.

Я хотел бы для этого напечатать что-то вроде: В классе A, Main.В классе B, метод B.В классе C метод C.

StackTrace, кажется, дает мне много трудно читаемой информации.Есть ли более простой способ или способ сделать более легким для чтения StackTrace?Фактический код намного больше, и я не хочу помещать операторы печати в каждый метод, поэтому я подумал, что что-то вроде этого может облегчить отладку.Кроме того, я не могу использовать отладчик 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 ]

0 голосов
/ 18 мая 2018

Используя бесплатную версию 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 вы можете применять такие вещи на уровне базового класса и автоматически применять их и к дочерним элементам (ссылка SO здесь ), но для того, чтобы применить атрибут к вашим методам, нужнопростой способ получить то, что вы хотите.

0 голосов
/ 18 мая 2018

Так что для всех, кто откликнулся на мою оригинальную ветку, вас может заинтересовать то, что я придумал до сих пор.Может быть, вы, ребята, или кто-то еще, можете добавить к этой дискуссии, и мы сможем найти более постоянное решение.Но вот что мне ближе всего подходит для автоматизации этого:

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.Diagnostics;using 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) Несколько вещей, на которые я хотел бы обратить ваше внимание, ребята: Iдумал, что закомментированный цикл 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: если вы раскомментируете ее,он дает вам весь поток выполнения правильно (не будет публиковать результаты, потому что он включает в себя личную информацию).Однако это означает, что мне нужно углубиться в код, найти метод, который вызывается последним, и добавить в него эту строку кода.

6) Источники: Насколько эффективен StackFrame?

Как найти метод, который вызвал текущий метод?

C # получает свое собственное имя класса

Пожалуйста, дайте мне знать, что вы, ребята, думаете.Благодарю.

...