Как получить CallerFilePath и CallerLineNumber без использования атрибутов CallerInfo?
Для моего решения log4net у меня есть API-оболочка, которая использует атрибуты CallerInfo, например
public void Write(string message,
[CallerMemberName] string memberName = "",
[CallerFilePath] string filePath = "",
[CallerLineNumber] int lineNumber = 0)
Тем не менее, я также использую Unity Interception, чтобы я мог выполнять запись трассировки ответов до / после, например, используя ICallHandler, как показано ниже в методе Invoke.
public class TraceCallHandler : ICallHandler
{
...
public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{
//---- Trace method inputs
this.LogInfoBeforeInvoke(input);
//---- invoking the target method
InvokeHandlerDelegate next = getNext();
IMethodReturn methodReturn = next(input, getNext);
//---- invoking the target method
this.LogInfoAfterInvoke(methodReturn.ReturnValue);
}
}
Примечание: приведенный выше код ни в коем случае не является полным / правильным... но просто хотел показать вам, что я делал для Unity Interception.
Мой вопрос / проблема заключается в следующем: когда я в конечном итоге вызываю log.Write(...), мне нужна информация о вызывающем абоненте цели, а не моя информация TraceCallHandler.
например, для имени метода, я могу сделать это:
string methodName = input.MethodBase.Name;
Как получить путь к файлу звонящего и номер линии звонящего? Возможно ли это сделать с помощью отражения?
Спасибо!
2 ответа
Да, вы можете получить их, используя отражение:
var sf = new System.Diagnostics.StackTrace(1).GetFrame(0);
Console.WriteLine(" File: {0}", sf.GetFileName());
Console.WriteLine(" Line Number: {0}", sf.GetFileLineNumber());
// Note that the column number defaults to zero
// when not initialized.
Console.WriteLine(" Column Number: {0}", sf.GetFileColumnNumber());
Однако, как ясно сказано в документации:
Информация StackFrame будет наиболее информативной с конфигурациями сборки Debug. По умолчанию сборки отладки содержат символы отладки, а сборки выпуска - нет. Символы отладки содержат большую часть файла, имени метода, номера строки и информации о столбцах, используемых при создании объектов StackFrame.
Поэтому, если вам нужна только отладка, включите ее в отладочных сборках и выйдите из системы. В сборках Release это будет, в лучшем случае, бесполезно, а в худшем - просто вводит в заблуждение, так как помимо соображений о символах, приведенных выше, компилятор будет агрессивно использовать встроенные методы, упорядочивать вещи и, как правило, портить ваши вещи.
Я только столкнулся с этой проблемой и думал, что поделюсь тем, что я изучил. Во-первых, когда вы включаете [CallerFilePath] в аргумент метода, побочным эффектом является то, что полный путь файла, включая любые идентифицируемые пользователем данные, будет включен в ваш.exe. Я создал простую программу с одним методом. Я создал exe. Затем я добавил атрибут [CallerFilePath] в тестовую функцию. Когда я сравнил результаты strings.exe (от sysinternals), тот, у которого был атрибут, отличался тем, что в нем содержался полный путь к моему исходному файлу.
c:\users\<my name>\documents\visual studio 2015\Projects\TestCallerAttribute\TestCallerAttribute\Program.cs
Приведенный выше ответ от stuartd является правильным, так как вы не сможете получить нужные данные из трассировки стека в сборке выпуска.
Однако существует решение для получения надежных данных: трассировка событий для Windows. Из msdn: "Event Tracing for Windows (ETW) - это эффективная функция трассировки на уровне ядра, которая позволяет записывать события ядра или приложения в файл журнала. Вы можете использовать события в режиме реального времени или из файла журнала и использовать их отладить приложение или определить, где возникают проблемы с производительностью в приложении."
Это не быстрое решение. Есть работа по настройке событий и слушателей, чтобы получить провенанс, который вам нужен. Долгосрочный выигрыш сильный.