Wie kann ich beim Anmelden in C # den Namen der Methode erfahren, die die aktuelle Methode aufgerufen hat? Ich weiß alles über System.Reflection.MethodBase.GetCurrentMethod()
, aber ich möchte in der Stapelverfolgung einen Schritt darunter gehen. Ich habe überlegt, den Stack-Trace zu analysieren, hoffe aber, einen saubereren, expliziteren Weg zu finden, etwa Assembly.GetCallingAssembly()
für Methoden.
c#
.net
logging
stack-trace
system.diagnostics
Flipdoubt
quelle
quelle
StackTrace
,StackFrame
undCallerMemberName
) und veröffentlicht die Ergebnisse als Kern für die anderen hier zu sehen: gist.github.com/wilson0x4d/7b30c3913e74adf4ad99b09163a57a1fAntworten:
Versuche dies:
Einzeiler:
Es ist von Get Calling Method using Reflection [C #] .
quelle
In C # 5 können Sie diese Informationen mithilfe der Anruferinformationen abrufen :
Sie können auch das
[CallerFilePath]
und bekommen[CallerLineNumber]
.quelle
[CallerTypeName]
aus dem aktuellen .Net Framework (4.6.2) und Core CLRSie können Anruferinformationen und optionale Parameter verwenden:
Dieser Test veranschaulicht dies:
Während der StackTrace oben ziemlich schnell arbeitet und in den meisten Fällen kein Leistungsproblem darstellt, sind die Anruferinformationen noch viel schneller. In einem Beispiel von 1000 Iterationen habe ich es 40-mal schneller getaktet.
quelle
CachingHelpers.WhoseThere("wrong name!");
==>,"wrong name!"
da dasCallerMemberName
nur den Standardwert ersetzt.this
Parameter an eine Erweiterungsmethode übergeben. Auch Olivier ist richtig, Sie können einen Wert übergeben und[CallerMemberName]
wird nicht angewendet; Stattdessen fungiert es als Überschreibung, bei der normalerweise der Standardwert verwendet wird. Wenn wir uns die IL ansehen, können wir tatsächlich sehen, dass die resultierende Methode nicht anders ist als die, die normalerweise für ein[opt]
Arg ausgegeben worden wäre. Die Injektion vonCallerMemberName
ist daher ein CLR-Verhalten. Schließlich die Dokumente: "Die Anruferinfo-Attribute [...] wirken sich auf den Standardwert aus, der übergeben wird, wenn das Argument weggelassen wird "async
freundlich, wasStackFrame
Ihnen nicht helfen wird. Hat auch keinen Einfluss darauf, von einem Lambda angerufen zu werden.Eine kurze Zusammenfassung der beiden Ansätze, wobei der Geschwindigkeitsvergleich der wichtige Teil ist.
http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx
Ermitteln des Aufrufers zur Kompilierungszeit
Ermitteln des Anrufers anhand des Stapels
Vergleich der beiden Ansätze
quelle
Wir können den Code von Herrn Assad (die derzeit akzeptierte Antwort) ein wenig verbessern, indem wir nur den Frame instanziieren, den wir tatsächlich benötigen, und nicht den gesamten Stapel:
Dies könnte etwas besser funktionieren, obwohl es aller Wahrscheinlichkeit nach immer noch den vollen Stapel verwenden muss, um diesen einzelnen Frame zu erstellen. Außerdem weist es immer noch die gleichen Einschränkungen auf, auf die Alex Lyman hingewiesen hat (Optimierer / nativer Code können die Ergebnisse verfälschen). Schließlich möchten Sie vielleicht überprüfen, ob Sie zurückkehren
new StackFrame(1)
oder.GetFrame(1)
nichtnull
, so unwahrscheinlich diese Möglichkeit auch sein mag.Siehe diese verwandte Frage: Können Sie mithilfe von Reflection den Namen der aktuell ausgeführten Methode ermitteln?
quelle
new ClassName(…)
gleich null ist?Im Allgemeinen können Sie die
System.Diagnostics.StackTrace
KlasseSystem.Diagnostics.StackFrame
verwendenGetMethod()
, um einSystem.Reflection.MethodBase
Objekt abzurufen , und dann die Methode verwenden, um ein Objekt abzurufen. Dieser Ansatz weist jedoch einige Einschränkungen auf:( HINWEIS: Ich werde nur auf die Antwort von Firas Assad eingehen .)
quelle
Ab .NET 4.5 können Sie Anruferinformationsattribute verwenden :
CallerFilePath
- Die Quelldatei, die die Funktion aufgerufen hat;CallerLineNumber
- Codezeile, die die Funktion aufgerufen hat;CallerMemberName
- Mitglied, das die Funktion aufgerufen hat.Diese Funktion ist auch in ".NET Core" und ".NET Standard" vorhanden.
Verweise
CallerFilePathAttribute
KlasseCallerLineNumberAttribute
KlasseCallerMemberNameAttribute
Klassequelle
Beachten Sie, dass dies im Release-Code aufgrund der Optimierung unzuverlässig ist. Wenn Sie die Anwendung im Sandbox-Modus (Netzwerkfreigabe) ausführen, können Sie den Stack-Frame überhaupt nicht abrufen.
Betrachten Sie aspektorientierte Programmierung (AOP) wie PostSharp , die Ihren Code nicht aufruft , sondern Ihren Code ändert und somit jederzeit weiß, wo er sich befindet.
quelle
Natürlich ist dies eine späte Antwort, aber ich habe eine bessere Option, wenn Sie .NET 4.5 oder mehr verwenden können:
Dadurch werden das aktuelle Datum und die aktuelle Uhrzeit gedruckt, gefolgt von "Namespace.ClassName.MethodName" und endend mit ": text".
Beispielausgabe:
Beispielverwendung:
quelle
quelle
Vielleicht suchen Sie so etwas:
quelle
Eine fantastische Klasse ist hier: http://www.csharp411.com/c-get-calling-method/
quelle
Ein anderer Ansatz, den ich verwendet habe, besteht darin, der fraglichen Methode einen Parameter hinzuzufügen.
void Foo()
Verwenden Sie beispielsweise anstelle vonvoid Foo(string context)
. Übergeben Sie dann eine eindeutige Zeichenfolge, die den aufrufenden Kontext angibt.Wenn Sie nur den Aufrufer / Kontext für die Entwicklung benötigen, können Sie den
param
vor dem Versand entfernen .quelle
Versuchen Sie Folgendes, um den Methodennamen und den Klassennamen zu erhalten:
quelle
wird genug sein, denke ich.
quelle
Sehen Sie sich den Namen der Protokollierungsmethode in .NET an . Achten Sie darauf, es nicht im Produktionscode zu verwenden. StackFrame ist möglicherweise nicht zuverlässig ...
quelle
Wir können auch Lambdas verwenden, um den Anrufer zu finden.
Angenommen, Sie haben eine von Ihnen definierte Methode:
und Sie möchten den Anrufer finden.
1 . Ändern Sie die Methodensignatur so, dass wir einen Parameter vom Typ Aktion haben (Func funktioniert auch):
2 . Lambda-Namen werden nicht zufällig generiert. Die Regel scheint zu sein:> <CallerMethodName> __X wobei CallerMethodName durch die vorherige Funktion ersetzt wird und X ein Index ist.
3 . Wenn wir MethodA aufrufen, muss der Action / Func-Parameter von der Aufrufermethode generiert werden. Beispiel:
4 . In MethodA können wir jetzt die oben definierte Hilfsfunktion aufrufen und die MethodInfo der Aufrufermethode finden.
Beispiel:
quelle
Zusätzliche Informationen zur Antwort von Firas Assaad.
Ich habe
new StackFrame(1).GetMethod().Name;
in .net Core 2.1 mit Abhängigkeitsinjektion verwendet und erhalte die aufrufende Methode als 'Start'.Ich habe es mit versucht
[System.Runtime.CompilerServices.CallerMemberName] string callerName = ""
und es gibt mir die richtige Aufrufmethodequelle
quelle