Come ottenere il nome del file di origine e il numero di riga di un membro del tipo?

Considerando che il file di dati di debug è disponibile (PDB) e utilizzando System.Reflection o un altro framework simile come Mono.Cecil , come recuperare a livello di codice il nome del file di origine e il numero di riga in cui un tipo o un membro di un tipo è dichiarato.

Ad esempio, supponiamo che tu abbia compilato questo file in un assembly:

C: \ MyProject \ Foo.cs

1: public class Foo 2: { 3: public string SayHello() 4: { 5: return "Hello"; 6: } 7: } 

Come fare qualcosa come:

 MethodInfo methodInfo = typeof(Foo).GetMethod("SayHello"); string sourceFileName = methodInfo.GetSourceFile(); // ?? Does not exist! int sourceLineNumber = methodInfo.GetLineNumber(); // ?? Does not exist! 

sourceFileName dovrebbe contenere “C: \ MyProject \ Foo.cs” e sourceLineNumber essere uguale a 3.

Aggiornamento: System.Diagnostics.StackFrame è effettivamente in grado di ottenere tali informazioni, ma solo nell’ambito dello stack di chiamate in esecuzione corrente. Significa che il metodo deve essere invocato per primo. Vorrei ottenere le stesse informazioni, ma senza invocare il membro del tipo.

Metodo aggiornato:

 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); } 

Nuova Framework API che popola gli argomenti (contrassegnati con attributi speciali) in fase di runtime, vedere di più nella mia risposta a questa domanda SO

Utilizzando il lettore PDB fornito dal CCI Metadata Project , è ansible estrarre la posizione del codice di un determinato membro del tipo. Vedere un’implementazione di esempio nel codice sorgente di OSS Gallio Project .

potresti trovare aiuto con questi collegamenti:

Anche i file e i numeri di riga senza la distribuzione dei file PDB hanno trovato questo post successivo

“Ciao Mark,

Quanto segue ti fornirà il numero di riga del tuo codice (nel file sorgente):

 Dim CurrentStack As System.Diagnostics.StackTrace MsgBox (CurrentStack.GetFrame(0).GetFileLineNumber) 

Nel caso in cui sei interessato, puoi scoprire la routine in cui ti trovi, così come tutti i suoi chiamanti.

 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 

Questo può essere molto utile se si desidera una routine di errore generalizzata perché può ottenere il nome del chiamante (che sarebbe dove si è verificato l’errore).

Cordiali saluti, Fergus MVP [pulsante Start di Windows, dialogo Shutdown] ”

Utilizzando uno dei metodi illustrati sopra, all’interno del costruttore di un attributo, è ansible fornire la posizione di origine di tutto, che può avere un attributo, ad esempio una class. Vedi la seguente class di attributi:

 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 { ... } 

Puoi scrivere per esempio:

 Console.WriteLine(typeof(Test).GetCustomAttribute(true)); 

L’output sarà:

 a:\develop\HWClassLibrary.cs\src\Tester\Program.cs(65): 

L’esempio di codice al seguente URL fornisce una class che puoi facilmente modificare per ottenere le informazioni che stai cercando:

http://blogs.msdn.com/rmbyers/pages/code-sample-stacktrace-with-manual-symbol-lookup.aspx