Related
When logging in C#, how can I learn the name of the method that called the current method? I know all about System.Reflection.MethodBase.GetCurrentMethod(), but I want to go one step beneath this in the stack trace. I've considered parsing the stack trace, but I am hoping to find a cleaner more explicit way, something like Assembly.GetCallingAssembly() but for methods.
Try this:
using System.Diagnostics;
// Get call stack
StackTrace stackTrace = new StackTrace();
// Get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
one-liner:
(new System.Diagnostics.StackTrace()).GetFrame(1).GetMethod().Name
It is from Get Calling Method using Reflection [C#].
In C# 5, you can get that information using caller info:
//using System.Runtime.CompilerServices;
public void SendError(string Message, [CallerMemberName] string callerName = "")
{
Console.WriteLine(callerName + "called me.");
}
You can also get the [CallerFilePath] and [CallerLineNumber].
You can use Caller Information and optional parameters:
public static string WhoseThere([CallerMemberName] string memberName = "")
{
return memberName;
}
This 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"));
}
While the StackTrace works quite fast above and would not be a performance issue in most cases the Caller Information is much faster still. In a sample of 1000 iterations, I clocked it as 40 times faster.
A quick recap of the 2 approaches with speed comparison being the important part.
http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx
Determining 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);
}
Determining the caller using the stack
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 the 2 approaches
Time for 1,000,000 iterations with Attributes: 196 ms
Time for 1,000,000 iterations with StackTrace: 5096 ms
So you see, using the attributes is much, much faster! Nearly 25x
faster in fact.
We can improve on Mr Assad's code (the current accepted answer) just a little bit by instantiating only the frame we actually need rather than the entire stack:
new StackFrame(1).GetMethod().Name;
This might perform a little better, though in all likelihood it still has to use the full stack to create that single frame. Also, it still has the same caveats that Alex Lyman pointed out (optimizer/native code might corrupt the results). Finally, you might want to check to be sure that new StackFrame(1) or .GetFrame(1) don't return null, as unlikely as that possibility might seem.
See this related question:
Can you use reflection to find the name of the currently executing method?
In general, you can use the System.Diagnostics.StackTrace class to get a System.Diagnostics.StackFrame, and then use the GetMethod() method to get a System.Reflection.MethodBase object. However, there are some caveats to this approach:
It represents the runtime stack -- optimizations could inline a method, and you will not see that method in the stack trace.
It will not show any native frames, so if there's even a chance your method is being called by a native method, this will not work, and there is in-fact no currently available way to do it.
(NOTE: I am just expanding on the answer provided by Firas Assad.)
As of .NET 4.5 you can use Caller Information Attributes:
CallerFilePath - The source file that called the function;
CallerLineNumber - Line of code that called the function;
CallerMemberName - Member that called 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 facility is also present in ".NET Core" and ".NET Standard".
References
Microsoft - Caller Information (C#)
Microsoft - CallerFilePathAttribute Class
Microsoft - CallerLineNumberAttribute Class
Microsoft - CallerMemberNameAttribute Class
Obviously this is a late answer, but I have a better option if you can use .NET 4.5 or newer:
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 ending with ": text".
Sample output:
6/17/2016 12:41:49 PM => WpfApplication.MainWindow..ctor: MainWindow initialized
Sample use:
Logger.WriteInformation<MainWindow>("MainWindow initialized");
Note that doing so will be unreliable in release code, due to optimization. Additionally, running the application in sandbox mode (network share) won't allow you to grab the stack frame at all.
Consider aspect-oriented programming (AOP), like PostSharp, which instead of being called from your code, modifies your code, and thus knows where it is at all times.
/// <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;
}
Maybe 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
private static MethodBase GetCallingMethod()
{
return new StackFrame(2, false).GetMethod();
}
private static Type GetCallingType()
{
return new StackFrame(2, false).GetMethod().DeclaringType;
}
A fantastic class is here: http://www.csharp411.com/c-get-calling-method/
Another approach I have used is to add a parameter to the method in question. For example, instead of void Foo(), use void Foo(string context). Then pass in some unique string that indicates the calling context.
If you only need the caller/context for development, you can remove the param before shipping.
For getting Method Name and Class Name try this:
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 );
}
Extra information to Firas Assaad answer.
I have used new StackFrame(1).GetMethod().Name; in .net core 2.1 with dependency injection and I am getting calling method as 'Start'.
I tried with [System.Runtime.CompilerServices.CallerMemberName] string callerName = ""
and it gives me correct calling method
We can also use lambda's in order to find the caller.
Suppose you have a method defined by you:
public void MethodA()
{
/*
* Method code here
*/
}
and you want to find it's caller.
1. Change the method signature so we have a parameter of type Action (Func will also work):
public void MethodA(Action helperAction)
{
/*
* Method code here
*/
}
2. Lambda names are not generated randomly. The rule seems to be: > <CallerMethodName>__X
where CallerMethodName is replaced by the previous function and X is an 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 has to be generated by the caller method.
Example:
MethodA(() => {});
4. Inside MethodA we can now call the helper function defined above and find the MethodInfo of the caller method.
Example:
MethodInfo callingMethodInfo = GetCallingMethodInfo(serverCall.Method.Name);
StackFrame caller = (new System.Diagnostics.StackTrace()).GetFrame(1);
string methodName = caller.GetMethod().Name;
will be enough, I think.
When logging in C#, how can I learn the name of the method that called the current method? I know all about System.Reflection.MethodBase.GetCurrentMethod(), but I want to go one step beneath this in the stack trace. I've considered parsing the stack trace, but I am hoping to find a cleaner more explicit way, something like Assembly.GetCallingAssembly() but for methods.
Try this:
using System.Diagnostics;
// Get call stack
StackTrace stackTrace = new StackTrace();
// Get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
one-liner:
(new System.Diagnostics.StackTrace()).GetFrame(1).GetMethod().Name
It is from Get Calling Method using Reflection [C#].
In C# 5, you can get that information using caller info:
//using System.Runtime.CompilerServices;
public void SendError(string Message, [CallerMemberName] string callerName = "")
{
Console.WriteLine(callerName + "called me.");
}
You can also get the [CallerFilePath] and [CallerLineNumber].
You can use Caller Information and optional parameters:
public static string WhoseThere([CallerMemberName] string memberName = "")
{
return memberName;
}
This 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"));
}
While the StackTrace works quite fast above and would not be a performance issue in most cases the Caller Information is much faster still. In a sample of 1000 iterations, I clocked it as 40 times faster.
A quick recap of the 2 approaches with speed comparison being the important part.
http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx
Determining 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);
}
Determining the caller using the stack
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 the 2 approaches
Time for 1,000,000 iterations with Attributes: 196 ms
Time for 1,000,000 iterations with StackTrace: 5096 ms
So you see, using the attributes is much, much faster! Nearly 25x
faster in fact.
We can improve on Mr Assad's code (the current accepted answer) just a little bit by instantiating only the frame we actually need rather than the entire stack:
new StackFrame(1).GetMethod().Name;
This might perform a little better, though in all likelihood it still has to use the full stack to create that single frame. Also, it still has the same caveats that Alex Lyman pointed out (optimizer/native code might corrupt the results). Finally, you might want to check to be sure that new StackFrame(1) or .GetFrame(1) don't return null, as unlikely as that possibility might seem.
See this related question:
Can you use reflection to find the name of the currently executing method?
In general, you can use the System.Diagnostics.StackTrace class to get a System.Diagnostics.StackFrame, and then use the GetMethod() method to get a System.Reflection.MethodBase object. However, there are some caveats to this approach:
It represents the runtime stack -- optimizations could inline a method, and you will not see that method in the stack trace.
It will not show any native frames, so if there's even a chance your method is being called by a native method, this will not work, and there is in-fact no currently available way to do it.
(NOTE: I am just expanding on the answer provided by Firas Assad.)
As of .NET 4.5 you can use Caller Information Attributes:
CallerFilePath - The source file that called the function;
CallerLineNumber - Line of code that called the function;
CallerMemberName - Member that called 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 facility is also present in ".NET Core" and ".NET Standard".
References
Microsoft - Caller Information (C#)
Microsoft - CallerFilePathAttribute Class
Microsoft - CallerLineNumberAttribute Class
Microsoft - CallerMemberNameAttribute Class
Obviously this is a late answer, but I have a better option if you can use .NET 4.5 or newer:
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 ending with ": text".
Sample output:
6/17/2016 12:41:49 PM => WpfApplication.MainWindow..ctor: MainWindow initialized
Sample use:
Logger.WriteInformation<MainWindow>("MainWindow initialized");
Note that doing so will be unreliable in release code, due to optimization. Additionally, running the application in sandbox mode (network share) won't allow you to grab the stack frame at all.
Consider aspect-oriented programming (AOP), like PostSharp, which instead of being called from your code, modifies your code, and thus knows where it is at all times.
/// <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;
}
Maybe 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
private static MethodBase GetCallingMethod()
{
return new StackFrame(2, false).GetMethod();
}
private static Type GetCallingType()
{
return new StackFrame(2, false).GetMethod().DeclaringType;
}
A fantastic class is here: http://www.csharp411.com/c-get-calling-method/
Another approach I have used is to add a parameter to the method in question. For example, instead of void Foo(), use void Foo(string context). Then pass in some unique string that indicates the calling context.
If you only need the caller/context for development, you can remove the param before shipping.
For getting Method Name and Class Name try this:
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 );
}
Extra information to Firas Assaad answer.
I have used new StackFrame(1).GetMethod().Name; in .net core 2.1 with dependency injection and I am getting calling method as 'Start'.
I tried with [System.Runtime.CompilerServices.CallerMemberName] string callerName = ""
and it gives me correct calling method
We can also use lambda's in order to find the caller.
Suppose you have a method defined by you:
public void MethodA()
{
/*
* Method code here
*/
}
and you want to find it's caller.
1. Change the method signature so we have a parameter of type Action (Func will also work):
public void MethodA(Action helperAction)
{
/*
* Method code here
*/
}
2. Lambda names are not generated randomly. The rule seems to be: > <CallerMethodName>__X
where CallerMethodName is replaced by the previous function and X is an 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 has to be generated by the caller method.
Example:
MethodA(() => {});
4. Inside MethodA we can now call the helper function defined above and find the MethodInfo of the caller method.
Example:
MethodInfo callingMethodInfo = GetCallingMethodInfo(serverCall.Method.Name);
StackFrame caller = (new System.Diagnostics.StackTrace()).GetFrame(1);
string methodName = caller.GetMethod().Name;
will be enough, I think.
When logging in C#, how can I learn the name of the method that called the current method? I know all about System.Reflection.MethodBase.GetCurrentMethod(), but I want to go one step beneath this in the stack trace. I've considered parsing the stack trace, but I am hoping to find a cleaner more explicit way, something like Assembly.GetCallingAssembly() but for methods.
Try this:
using System.Diagnostics;
// Get call stack
StackTrace stackTrace = new StackTrace();
// Get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
one-liner:
(new System.Diagnostics.StackTrace()).GetFrame(1).GetMethod().Name
It is from Get Calling Method using Reflection [C#].
In C# 5, you can get that information using caller info:
//using System.Runtime.CompilerServices;
public void SendError(string Message, [CallerMemberName] string callerName = "")
{
Console.WriteLine(callerName + "called me.");
}
You can also get the [CallerFilePath] and [CallerLineNumber].
You can use Caller Information and optional parameters:
public static string WhoseThere([CallerMemberName] string memberName = "")
{
return memberName;
}
This 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"));
}
While the StackTrace works quite fast above and would not be a performance issue in most cases the Caller Information is much faster still. In a sample of 1000 iterations, I clocked it as 40 times faster.
A quick recap of the 2 approaches with speed comparison being the important part.
http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx
Determining 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);
}
Determining the caller using the stack
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 the 2 approaches
Time for 1,000,000 iterations with Attributes: 196 ms
Time for 1,000,000 iterations with StackTrace: 5096 ms
So you see, using the attributes is much, much faster! Nearly 25x
faster in fact.
We can improve on Mr Assad's code (the current accepted answer) just a little bit by instantiating only the frame we actually need rather than the entire stack:
new StackFrame(1).GetMethod().Name;
This might perform a little better, though in all likelihood it still has to use the full stack to create that single frame. Also, it still has the same caveats that Alex Lyman pointed out (optimizer/native code might corrupt the results). Finally, you might want to check to be sure that new StackFrame(1) or .GetFrame(1) don't return null, as unlikely as that possibility might seem.
See this related question:
Can you use reflection to find the name of the currently executing method?
In general, you can use the System.Diagnostics.StackTrace class to get a System.Diagnostics.StackFrame, and then use the GetMethod() method to get a System.Reflection.MethodBase object. However, there are some caveats to this approach:
It represents the runtime stack -- optimizations could inline a method, and you will not see that method in the stack trace.
It will not show any native frames, so if there's even a chance your method is being called by a native method, this will not work, and there is in-fact no currently available way to do it.
(NOTE: I am just expanding on the answer provided by Firas Assad.)
As of .NET 4.5 you can use Caller Information Attributes:
CallerFilePath - The source file that called the function;
CallerLineNumber - Line of code that called the function;
CallerMemberName - Member that called 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 facility is also present in ".NET Core" and ".NET Standard".
References
Microsoft - Caller Information (C#)
Microsoft - CallerFilePathAttribute Class
Microsoft - CallerLineNumberAttribute Class
Microsoft - CallerMemberNameAttribute Class
Obviously this is a late answer, but I have a better option if you can use .NET 4.5 or newer:
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 ending with ": text".
Sample output:
6/17/2016 12:41:49 PM => WpfApplication.MainWindow..ctor: MainWindow initialized
Sample use:
Logger.WriteInformation<MainWindow>("MainWindow initialized");
Note that doing so will be unreliable in release code, due to optimization. Additionally, running the application in sandbox mode (network share) won't allow you to grab the stack frame at all.
Consider aspect-oriented programming (AOP), like PostSharp, which instead of being called from your code, modifies your code, and thus knows where it is at all times.
/// <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;
}
Maybe 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
private static MethodBase GetCallingMethod()
{
return new StackFrame(2, false).GetMethod();
}
private static Type GetCallingType()
{
return new StackFrame(2, false).GetMethod().DeclaringType;
}
A fantastic class is here: http://www.csharp411.com/c-get-calling-method/
Another approach I have used is to add a parameter to the method in question. For example, instead of void Foo(), use void Foo(string context). Then pass in some unique string that indicates the calling context.
If you only need the caller/context for development, you can remove the param before shipping.
For getting Method Name and Class Name try this:
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 );
}
Extra information to Firas Assaad answer.
I have used new StackFrame(1).GetMethod().Name; in .net core 2.1 with dependency injection and I am getting calling method as 'Start'.
I tried with [System.Runtime.CompilerServices.CallerMemberName] string callerName = ""
and it gives me correct calling method
We can also use lambda's in order to find the caller.
Suppose you have a method defined by you:
public void MethodA()
{
/*
* Method code here
*/
}
and you want to find it's caller.
1. Change the method signature so we have a parameter of type Action (Func will also work):
public void MethodA(Action helperAction)
{
/*
* Method code here
*/
}
2. Lambda names are not generated randomly. The rule seems to be: > <CallerMethodName>__X
where CallerMethodName is replaced by the previous function and X is an 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 has to be generated by the caller method.
Example:
MethodA(() => {});
4. Inside MethodA we can now call the helper function defined above and find the MethodInfo of the caller method.
Example:
MethodInfo callingMethodInfo = GetCallingMethodInfo(serverCall.Method.Name);
StackFrame caller = (new System.Diagnostics.StackTrace()).GetFrame(1);
string methodName = caller.GetMethod().Name;
will be enough, I think.
I want to add more info to the logger at the call method level, and i need to know if exist possibility to get StackTrace of methods calls inside call method.
UPDATE: The purpose of this is to draw the flow of all methods called until the certain step inside call method.
EXAMPLE:
public class Type1
{
internal string method2_T1() {
return new Type2().method1_T2();
}
}
public class Type2
{
public string method1_T2()
{
return "Type2.method1_T2";
}
}
static void Main(string[] args)
{
string t = new Type1().method2_T1();
LogNow();
....
}
and the result to obtain, when I call LogNow(), are:
StackTrace of method2_T1()
...
Thanks
It's pretty easy:
var stackTrace = new StackTrace(true);
var traceToLog = stackTrace.ToString();
The true argument says to include the file info.
Todd Sprang's answer is good as the actual answer, but be aware that the stack trace will change in unpredictable ways when you move to a RELEASE build, or use async/await. Don't rely programatically on the answers because you may come unstuck when you put the code into production.
If you want to know the direct caller of a particular function, in a way Microsoft recommend, there's the useful trick using the [CallerMemberName], [CallerFilePath], and [CallerLineNumber] attributes. Mark up optional parameters like so;
public void LogWithCallerInfo(
string message,
[CallerMemberName] string memberName = "Caller",
[CallerFilePath] string sourceFilePath = "File",
[CallerLineNumber] int sourceLineNumber = 0)
{
WriteProgressMessage(..., memberName, sourceFilePath, sourceLineNumber);
}
and call like this;
LogWithCallerInfo("my message");
The three optional parameters will be replaced with the appropriate call info.
When logging in C#, how can I learn the name of the method that called the current method? I know all about System.Reflection.MethodBase.GetCurrentMethod(), but I want to go one step beneath this in the stack trace. I've considered parsing the stack trace, but I am hoping to find a cleaner more explicit way, something like Assembly.GetCallingAssembly() but for methods.
Try this:
using System.Diagnostics;
// Get call stack
StackTrace stackTrace = new StackTrace();
// Get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
one-liner:
(new System.Diagnostics.StackTrace()).GetFrame(1).GetMethod().Name
It is from Get Calling Method using Reflection [C#].
In C# 5, you can get that information using caller info:
//using System.Runtime.CompilerServices;
public void SendError(string Message, [CallerMemberName] string callerName = "")
{
Console.WriteLine(callerName + "called me.");
}
You can also get the [CallerFilePath] and [CallerLineNumber].
You can use Caller Information and optional parameters:
public static string WhoseThere([CallerMemberName] string memberName = "")
{
return memberName;
}
This 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"));
}
While the StackTrace works quite fast above and would not be a performance issue in most cases the Caller Information is much faster still. In a sample of 1000 iterations, I clocked it as 40 times faster.
A quick recap of the 2 approaches with speed comparison being the important part.
http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx
Determining 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);
}
Determining the caller using the stack
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 the 2 approaches
Time for 1,000,000 iterations with Attributes: 196 ms
Time for 1,000,000 iterations with StackTrace: 5096 ms
So you see, using the attributes is much, much faster! Nearly 25x
faster in fact.
We can improve on Mr Assad's code (the current accepted answer) just a little bit by instantiating only the frame we actually need rather than the entire stack:
new StackFrame(1).GetMethod().Name;
This might perform a little better, though in all likelihood it still has to use the full stack to create that single frame. Also, it still has the same caveats that Alex Lyman pointed out (optimizer/native code might corrupt the results). Finally, you might want to check to be sure that new StackFrame(1) or .GetFrame(1) don't return null, as unlikely as that possibility might seem.
See this related question:
Can you use reflection to find the name of the currently executing method?
In general, you can use the System.Diagnostics.StackTrace class to get a System.Diagnostics.StackFrame, and then use the GetMethod() method to get a System.Reflection.MethodBase object. However, there are some caveats to this approach:
It represents the runtime stack -- optimizations could inline a method, and you will not see that method in the stack trace.
It will not show any native frames, so if there's even a chance your method is being called by a native method, this will not work, and there is in-fact no currently available way to do it.
(NOTE: I am just expanding on the answer provided by Firas Assad.)
As of .NET 4.5 you can use Caller Information Attributes:
CallerFilePath - The source file that called the function;
CallerLineNumber - Line of code that called the function;
CallerMemberName - Member that called 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 facility is also present in ".NET Core" and ".NET Standard".
References
Microsoft - Caller Information (C#)
Microsoft - CallerFilePathAttribute Class
Microsoft - CallerLineNumberAttribute Class
Microsoft - CallerMemberNameAttribute Class
Obviously this is a late answer, but I have a better option if you can use .NET 4.5 or newer:
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 ending with ": text".
Sample output:
6/17/2016 12:41:49 PM => WpfApplication.MainWindow..ctor: MainWindow initialized
Sample use:
Logger.WriteInformation<MainWindow>("MainWindow initialized");
Note that doing so will be unreliable in release code, due to optimization. Additionally, running the application in sandbox mode (network share) won't allow you to grab the stack frame at all.
Consider aspect-oriented programming (AOP), like PostSharp, which instead of being called from your code, modifies your code, and thus knows where it is at all times.
/// <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;
}
Maybe 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
private static MethodBase GetCallingMethod()
{
return new StackFrame(2, false).GetMethod();
}
private static Type GetCallingType()
{
return new StackFrame(2, false).GetMethod().DeclaringType;
}
A fantastic class is here: http://www.csharp411.com/c-get-calling-method/
Another approach I have used is to add a parameter to the method in question. For example, instead of void Foo(), use void Foo(string context). Then pass in some unique string that indicates the calling context.
If you only need the caller/context for development, you can remove the param before shipping.
For getting Method Name and Class Name try this:
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 );
}
Extra information to Firas Assaad answer.
I have used new StackFrame(1).GetMethod().Name; in .net core 2.1 with dependency injection and I am getting calling method as 'Start'.
I tried with [System.Runtime.CompilerServices.CallerMemberName] string callerName = ""
and it gives me correct calling method
We can also use lambda's in order to find the caller.
Suppose you have a method defined by you:
public void MethodA()
{
/*
* Method code here
*/
}
and you want to find it's caller.
1. Change the method signature so we have a parameter of type Action (Func will also work):
public void MethodA(Action helperAction)
{
/*
* Method code here
*/
}
2. Lambda names are not generated randomly. The rule seems to be: > <CallerMethodName>__X
where CallerMethodName is replaced by the previous function and X is an 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 has to be generated by the caller method.
Example:
MethodA(() => {});
4. Inside MethodA we can now call the helper function defined above and find the MethodInfo of the caller method.
Example:
MethodInfo callingMethodInfo = GetCallingMethodInfo(serverCall.Method.Name);
StackFrame caller = (new System.Diagnostics.StackTrace()).GetFrame(1);
string methodName = caller.GetMethod().Name;
will be enough, I think.