Ответ 1
Используя считыватель PDB, предоставленный Project метаданных CCI, можно извлечь местоположение кода для данного члена типа. См. Пример реализации в исходном коде OSS Gallio Project.
Учитывая, что файл данных отладки доступен (PDB) и с помощью System.Reflection или другой подобной структуры, такой как Mono.Cecil, как получить программную имя исходного файла и номер строки, в которой объявлен тип или член типа.
Например, скажем, вы скомпилировали этот файл в сборку:
C:\MyProject\Foo.cs
1: public class Foo
2: {
3: public string SayHello()
4: {
5: return "Hello";
6: }
7: }
Как сделать что-то вроде:
MethodInfo methodInfo = typeof(Foo).GetMethod("SayHello");
string sourceFileName = methodInfo.GetSourceFile(); // ?? Does not exist!
int sourceLineNumber = methodInfo.GetLineNumber(); // ?? Does not exist!
sourceFileName будет содержать "C:\MyProject\Foo.cs", а sourceLineNumber будет равно 3.
Обновление: System.Diagnostics.StackFrame
действительно может получить эту информацию, но только в области текущего исполняемого стека вызовов. Это означает, что сначала нужно вызвать метод. Я хотел бы получить ту же информацию, но не вызывая член типа.
Используя считыватель PDB, предоставленный Project метаданных CCI, можно извлечь местоположение кода для данного члена типа. См. Пример реализации в исходном коде OSS Gallio Project.
Современный метод:
private static void Log(string text,
[CallerFilePath] string file = "",
[CallerMemberName] string member = "",
[CallerLineNumber] int line = 0)
{
Console.WriteLine("{0}_{1}({2}): {3}", Path.GetFileName(file), member, line, text);
}
Новый Framework API
, который заполняет аргументы (отмеченные специальными атрибутами) во время выполнения,
см. больше в мой ответ на этот вопрос SO
вы можете найти помощь по этим ссылкам:
Получение номеров файлов и строк без развертывания файлов PDB также нашел следующее post
"Привет, Марк,
Следующее предоставит вам номер строки вашего кода (в исходный файл):
Dim CurrentStack As System.Diagnostics.StackTrace
MsgBox (CurrentStack.GetFrame(0).GetFileLineNumber)
Если вам интересно, вы можете узнать о том, что вы в, а также всех его вызывающих абонентов.
Public Function MeAndMyCaller As String
Dim CurrentStack As New System.Diagnostics.StackTrace
Dim Myself As String = CurrentStack.GetFrame(0).GetMethod.Name
Dim MyCaller As String = CurrentStack.GetFrame(1).GetMethod.Name
Return "In " & Myself & vbCrLf & "Called by " & MyCaller
End Function
Это может быть очень удобно, если вы хотите использовать генерализованную ошибку, поскольку она может получить имя вызывающего абонента (которое было бы там, где произошла ошибка).
С уважением, Фергус MVP [Кнопка запуска Windows, диалог завершения работы] "
Используя один из методов, описанных выше, внутри конструктора атрибута вы можете предоставить исходное местоположение всего, что может иметь атрибут - например, класс. См. Следующий класс атрибутов:
sealed class ProvideSourceLocation : Attribute
{
public readonly string File;
public readonly string Member;
public readonly int Line;
public ProvideSourceLocation
(
[CallerFilePath] string file = "",
[CallerMemberName] string member = "",
[CallerLineNumber] int line = 0)
{
File = file;
Member = member;
Line = line;
}
public override string ToString() { return File + "(" + Line + "):" + Member; }
}
[ProvideSourceLocation]
class Test
{
...
}
Вы можете написать, например:
Console.WriteLine(typeof(Test).GetCustomAttribute<ProvideSourceLocation>(true));
Выход будет:
a:\develop\HWClassLibrary.cs\src\Tester\Program.cs(65):
Пример кода в следующем URL-адресе предоставляет класс, который вы можете легко изменить, чтобы получить информацию, которую вы используете:
http://blogs.msdn.com/rmbyers/pages/code-sample-stacktrace-with-manual-symbol-lookup.aspx