How do I find a way to call the current method?

Posted by suspect on Fri, 24 Jan 2020 07:10:47 +0100

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("&gt;", 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 :

  1. It represents a runtime stack-optimization that can inline a method, and you won't see it in the stack trace.
  2. 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

  1. Microsoft-Caller Information (C)
  2. Microsoft-CallerFilePathAttribute class
  3. Microsoft-CallerLineNumberAttribute class
  4. Microsoft-CallerMemberNameAttribute class

#14th floor

Speed comparison is an important part of a quick review of the two methods.

http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx

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].

0 original articles published. 2. Visits 6089
Private letter follow

Topics: Lambda network Programming