How do I know the name of the method that calls the current method when I log in to C??I know all about System.Reflection.MethodBase.GetCurrentMethod(), but I want to be one level lower in stack tracking.I've considered resolving stack traces, but I want to find a clearer, clearer way, similar to Assembly.GetCallingAssembly(), but for methods.
#1st floor
You can use Caller Information and optional parameters:
public static string WhoseThere([CallerMemberName] string memberName = "") { return memberName; }
The test illustrates this:
[Test] public void Should_get_name_of_calling_method() { var methodName = CachingHelpers.WhoseThere(); Assert.That(methodName, Is.EqualTo("Should_get_name_of_calling_method")); }
Although StackTrace runs fast on it and is not a performance issue in most cases, caller information is still much faster.In the 1,000 iterations example, I increased it 40 times faster.
#2nd floor
StackFrame caller = (new System.Diagnostics.StackTrace()).GetFrame(1); string methodName = caller.GetMethod().Name;
I think that's enough.
#3rd floor
We can also use lambda to find callers.
Suppose you have a defined method:
public void MethodA() { /* * Method code here */ }
And you want to find its caller.
1.Change the method signature so that we have a parameter of type Action (Func can also use):
public void MethodA(Action helperAction) { /* * Method code here */ }
2.Lambda name is not randomly generated.The rule seems to be: > <CallerMethodName> u X, where CallerMethodName is replaced by the last function and X is the index.
private MethodInfo GetCallingMethodInfo(string funcName) { return GetType().GetMethod( funcName.Substring(1, funcName.IndexOf(">", 1, StringComparison.Ordinal) - 1) ); }
3.When we call MethodA, the Action / Func parameter must be generated by the caller method.Example:
MethodA(() => {});
4.Inside MethodA, we can now call the helper function defined above and find MethodInfo for the caller's method.
Example:
MethodInfo callingMethodInfo = GetCallingMethodInfo(serverCall.Method.Name);
#4th floor
Try this:
using System.Diagnostics; // Get call stack StackTrace stackTrace = new StackTrace(); // Get calling method name Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
It comes from Get Call Method Using Reflection [C] .
#5th floor
Note that because of optimization, this will be unreliable in the release code.In addition, running the application in sandbox mode (network sharing) will not allow you to grab stack frames at all.
Think about it like PostSharp such Aspect-oriented programming (AOP), instead of calling it from code, modify your code to always know where it is.
#6th floor
Have a look .NET In Logging Method name.Be careful to use it in production code.StackFrame may be unreliable...
#7th floor
Usually, you can use System.Diagnostics.StackTrace Class acquisition System.Diagnostics.StackFrame And then use GetMethod() Method acquisition System.Reflection.MethodBase Object.However, this method has Some warnings :
- It represents a runtime stack-optimization that can inline a method, and you won't see it in the stack trace.
- It does not display any native framework, so even if it is possible for your method to be invoked by the native method, it will not work properly and there are actually no methods available yet.
(Note: I'm just extending the Firas Assad offering Answer to . )
#8th floor
By instantiating only the framework we actually need, not the entire stack, we can make some improvements to Mr. Assad's code (the currently accepted answer):
new StackFrame(1).GetMethod().Name;
This may be better, although it is likely that a full stack will still have to be used to create a single frame.Furthermore, it still has warnings pointed out by Alex Lyman (optimizer/local code may break the results).Finally, you may need to check to make sure that the new StackFrame(1) or.GetFrame(1) does not return null, which seems unlikely.
See this related issue: Can reflection be used to find the name of the currently executing method?
#9th floor
Perhaps you are looking for something like this:
StackFrame frame = new StackFrame(1); frame.GetMethod().Name; //Gets the current method name MethodBase method = frame.GetMethod(); method.DeclaringType.Name //Gets the current class name
#10th floor
Another method I use is to add parameters to the problematic method.For example, use void Foo(string context) instead of void Foo() void Foo(string context).It then passes some unique strings representing the calling context.
If you only need caller/context development, you can delete the param before shipping.
#11th floor
/// <summary> /// Returns the call that occurred just before the "GetCallingMethod". /// </summary> public static string GetCallingMethod() { return GetCallingMethod("GetCallingMethod"); } /// <summary> /// Returns the call that occurred just before the the method specified. /// </summary> /// <param name="MethodAfter">The named method to see what happened just before it was called. (case sensitive)</param> /// <returns>The method name.</returns> public static string GetCallingMethod(string MethodAfter) { string str = ""; try { StackTrace st = new StackTrace(); StackFrame[] frames = st.GetFrames(); for (int i = 0; i < st.FrameCount - 1; i++) { if (frames[i].GetMethod().Name.Equals(MethodAfter)) { if (!frames[i + 1].GetMethod().Name.Equals(MethodAfter)) // ignores overloaded methods. { str = frames[i + 1].GetMethod().ReflectedType.FullName + "." + frames[i + 1].GetMethod().Name; break; } } } } catch (Exception) { ; } return str; }
#12th floor
var callingMethod = new StackFrame(1, true).GetMethod(); string source = callingMethod.ReflectedType.FullName + ": " + callingMethod.Name;
13th floor
Starting with.NET 4.5, you can use the Caller Information" Attributes:
- CallerFilePath The source file of the call function;
- CallerLineNumber The line of code that calls the function;
-
CallerMemberName A member that calls the function.
public void WriteLine( [CallerFilePath] string callerFilePath = "", [CallerLineNumber] long callerLineNumber = 0, [CallerMemberName] string callerMember= "") { Debug.WriteLine( "Caller File Path: {0}, Caller Line Number: {1}, Caller Member: {2}", callerFilePath, callerLineNumber, callerMember); }
This functionality is also present in'.NET Core'and'.NET Standard'.
Reference
- Microsoft-Caller Information (C)
- Microsoft-CallerFilePathAttribute class
- Microsoft-CallerLineNumberAttribute class
- Microsoft-CallerMemberNameAttribute class
#14th floor
Speed comparison is an important part of a quick review of the two methods.
Determine the caller at compile time
static void Log(object message, [CallerMemberName] string memberName = "", [CallerFilePath] string fileName = "", [CallerLineNumber] int lineNumber = 0) { // we'll just use a simple Console write for now Console.WriteLine("{0}({1}):{2} - {3}", fileName, lineNumber, memberName, message); }
Use stack to determine caller
static void Log(object message) { // frame 1, true for source info StackFrame frame = new StackFrame(1, true); var method = frame.GetMethod(); var fileName = frame.GetFileName(); var lineNumber = frame.GetFileLineNumber(); // we'll just use a simple Console write for now Console.WriteLine("{0}({1}):{2} - {3}", fileName, lineNumber, method.Name, message); }
Comparison of two methods
Time for 1,000,000 iterations with Attributes: 196 ms Time for 1,000,000 iterations with StackTrace: 5096 ms
So you can see that using attributes is much faster!It's almost 25 times faster.
#15th floor
Obviously, this is a later answer, but if you can use.NET 4.5 or later, I have a better choice:
internal static void WriteInformation<T>(string text, [CallerMemberName]string method = "") { Console.WriteLine(DateTime.Now.ToString() + " => " + typeof(T).FullName + "." + method + ": " + text); }
This will print the current date and time followed by "Namespace.ClassName.MethodName" and end with ": text".
Sample output:
6/17/2016 12:41:49 PM => WpfApplication.MainWindow..ctor: MainWindow initialized
Sample use:
Logger.WriteInformation<MainWindow>("MainWindow initialized");
16th floor
private static MethodBase GetCallingMethod() { return new StackFrame(2, false).GetMethod(); } private static Type GetCallingType() { return new StackFrame(2, false).GetMethod().DeclaringType; }
A great lesson here: http : //www.csharp411.com/c-get-calling-method/
#17 Floor
To get the method name and class name, try the following:
public static void Call() { StackTrace stackTrace = new StackTrace(); var methodName = stackTrace.GetFrame(1).GetMethod(); var className = methodName.DeclaringType.Name.ToString(); Console.WriteLine(methodName.Name + "*****" + className ); }
#18th floor
More information about Firas Assaad answers.
I've used the new StackFrame(1).GetMethod().Name; in.net core 2.1 with dependency injection, I'll call the method Start.
I tried to use [System.Runtime.CompilerServices.CallerMemberName] string callerName =', which provided me with the correct call method
#19th floor
In C# 5, you can use Caller Information Get this information:
//using System.Runtime.CompilerServices; public void SendError(string Message, [CallerMemberName] string callerName = "") { Console.WriteLine(callerName + "called me."); }
You can also get [CallerFilePath] and [CallerLineNumber].