2016-05-08 8 views
2

Я хочу реализовать универсальный регистратор, который поможет мне увидеть стек вызовов методов.Получить stacktrace внутри C# метод

Я знаю, что есть некоторые методы из System.Diagnostic, но они были введены в .net 4.0, и я боюсь, что он не будет работать на ядре xamarin или .net или что-то в этом роде. Поэтому я хочу иметь более универсальное решение.

Другой проблемой является async \ await, который вводит некоторый беспорядок.

Мне нужно пропустить дополнительный параметр в каждом методе, который хранит некоторый контекст и помогает мне определить стек вызовов, но это решение является немного сложным.

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

Есть ли другое решение?

+1

Вы могли бы, конечно, взломать вокруг: выбросить исключение, поймать его и читать стек вызовов от него :) – MarcinJuraszek

+0

@MarcinJuraszek Nice хак :), но я боюсь, что это будет влиять на производительность слишком много. – Neir0

ответ

2

Вы можете использовать только Environment.StackTrace. Это было частью Рамочной основы с самого начала.

Environment.StackTrace вернет полный стек (включая вызов Environment.StackTrance) в виде строки, разделенной по строкам.

Что-то вроде этого:

в System.Environment.GetStackTrace (Exception е, Boolean needFileInfo)
в System.Environment.get_StackTrace()
на WpfApplication2.MainWindow.GetStack (Int32 removeLines)
на WpfApplication2.MainWindow.Button_Click (отправитель Object, RoutedEventArgs е)
...
в System.Threading.ThreadHelper.ThreadStart()

Все, что вам нужно сделать, это разделить/разбор/форматировать его, независимо от того, что вы хотите с ним делать.

Поскольку вы будете использовать это в своих классах, не забудьте удалить новейшие строки X.

Этот код должен работать везде, поскольку он преднамеренно низкоуровневый.

private static string[] GetStack(int removeLines) 
{ 
    string[] stack = Environment.StackTrace.Split(
     new string[] {Environment.NewLine}, 
     StringSplitOptions.RemoveEmptyEntries); 

    if(stack.Length <= removeLines) 
     return new string[0]; 

    string[] actualResult = new string[stack.Length - removeLines]; 
    for (int i = removeLines; i < stack.Length; i++) 
     // Remove 6 characters (e.g. " at ") from the beginning of the line 
     // This might be different for other languages and platforms 
     actualResult[i - removeLines] = stack[i].Substring(6); 

    return actualResult; 
} 
+0

Perfect. Это работает! – Neir0

+1

Одна заметка .net имеет разный вывод трассировки стека для разных языков, поэтому необходимо быть осторожным при удалении слов «на» и других языках. – Neir0

+0

Хорошая мысль. Я включу это в ответ для дальнейшего использования. –