Как получить 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) - это эффективная функция трассировки на уровне ядра, которая позволяет записывать события ядра или приложения в файл журнала. Вы можете использовать события в режиме реального времени или из файла журнала и использовать их отладить приложение или определить, где возникают проблемы с производительностью в приложении."

Это не быстрое решение. Есть работа по настройке событий и слушателей, чтобы получить провенанс, который вам нужен. Долгосрочный выигрыш сильный.

Другие вопросы по тегам