当登录c#时,我如何才能知道调用当前方法的方法的名称?我知道所有关于System.Reflection.MethodBase.GetCurrentMethod(),但我想在堆栈跟踪中走一步。我考虑过解析堆栈跟踪,但我希望找到一种更清晰、更显式的方式,比如Assembly.GetCallingAssembly(),但用于方法。


当前回答

额外信息给Firas Assaad回答。

我已经使用了新的StackFrame(1).GetMethod().Name;在.net核心2.1依赖注入和我得到调用方法为“开始”。

我尝试使用[System.Runtime.CompilerServices。CallerMemberName = "" 并给出了正确的调用方法

其他回答

private static MethodBase GetCallingMethod()
{
  return new StackFrame(2, false).GetMethod();
}

private static Type GetCallingType()
{
  return new StackFrame(2, false).GetMethod().DeclaringType;
}

这里有一个很棒的课程:http://www.csharp411.com/c-get-calling-method/

我们也可以用来找到调用者。

假设你有一个你定义的方法:

public void MethodA()
    {
        /*
         * Method code here
         */
    }

你想找到它的调用者。

1. 改变方法签名,这样我们就有了一个Action类型的参数(Func也可以):

public void MethodA(Action helperAction)
        {
            /*
             * Method code here
             */
        }

2. Lambda名称不是随机生成的。规则似乎是:> <CallerMethodName>__X 其中CallerMethodName被前面的函数替换,X是一个索引。

private MethodInfo GetCallingMethodInfo(string funcName)
    {
        return GetType().GetMethod(
              funcName.Substring(1,
                                funcName.IndexOf("&gt;", 1, StringComparison.Ordinal) - 1)
              );
    }

3.当我们调用MethodA时,Action/Func参数必须由调用方方法生成。 例子:

MethodA(() => {});

4. 在MethodA内部,我们现在可以调用上面定义的helper函数,并找到调用方方法的MethodInfo。

例子:

MethodInfo callingMethodInfo = GetCallingMethodInfo(serverCall.Method.Name);

快速回顾一下这两种方法,速度比较是重要的部分。

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

在编译时确定调用者

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

使用堆栈确定调用者

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

两种方法的比较

Time for 1,000,000 iterations with Attributes: 196 ms
Time for 1,000,000 iterations with StackTrace: 5096 ms

因此,您可以看到,使用属性要快得多!近25 x 实际上更快。

显然这是一个迟来的答案,但如果你能使用。net 4.5或更新版本,我有一个更好的选择:

internal static void WriteInformation<T>(string text, [CallerMemberName]string method = "")
{
    Console.WriteLine(DateTime.Now.ToString() + " => " + typeof(T).FullName + "." + method + ": " + text);
}

这将打印当前的日期和时间,后面跟着“Namespace.ClassName”。并以“:text”结尾。 样例输出:

6/17/2016 12:41:49 PM => WpfApplication.MainWindow..ctor: MainWindow initialized

示例使用:

Logger.WriteInformation<MainWindow>("MainWindow initialized");
/// <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;
}