fli*_*ubt 465 .net c# logging system.diagnostics stack-trace
登录C#时,如何学习调用当前方法的方法的名称?我知道所有这些System.Reflection.MethodBase.GetCurrentMethod(),但我想在堆栈跟踪中向下迈出一步.我考虑过解析堆栈跟踪,但我希望找到一种更清晰,更明确的方法,比如Assembly.GetCallingAssembly()方法.
Fir*_*aad 477
试试这个:
using System.Diagnostics;
// Get call stack
StackTrace stackTrace = new StackTrace();
// Get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
Run Code Online (Sandbox Code Playgroud)
它来自使用反射[C#]的Get Calling Method.
Coi*_*oin 328
在C#5中,您可以使用来电者信息获取该信息:
//using System.Runtime.CompilerServices;
public void SendError(string Message, [CallerMemberName] string callerName = "")
{
Console.WriteLine(callerName + "called me.");
}
Run Code Online (Sandbox Code Playgroud)
你也可以得到[CallerFilePath]和[CallerLineNumber].
dov*_*ove 103
您可以使用来电者信息和可选参数:
public static string WhoseThere([CallerMemberName] string memberName = "")
{
return memberName;
}
Run Code Online (Sandbox Code Playgroud)
该测试说明了这一点:
[Test]
public void Should_get_name_of_calling_method()
{
var methodName = CachingHelpers.WhoseThere();
Assert.That(methodName, Is.EqualTo("Should_get_name_of_calling_method"));
}
Run Code Online (Sandbox Code Playgroud)
虽然StackTrace的工作速度非常快,但在大多数情况下都不会出现性能问题,但Caller Information的速度要快得多.在1000次迭代的样本中,我将其计时速度提高了40倍.
Joe*_*orn 61
我们可以通过仅实例化我们实际需要的帧而不是整个堆栈来改进阿萨德先生的代码(当前接受的答案):
new StackFrame(1).GetMethod().Name;
Run Code Online (Sandbox Code Playgroud)
这可能会更好一点,但很可能它仍然必须使用完整堆栈来创建该单帧.此外,它仍然有Alex Lyman指出的相同警告(优化器/本机代码可能会破坏结果).最后,您可能希望检查以确定new StackFrame(1)或.GetFrame(1)不返回null,因为这种可能性看起来不太可能.
请参阅此相关问题: 您是否可以使用反射来查找当前正在执行的方法的名称?
Ale*_*man 60
通常,您可以使用System.Diagnostics.StackTrace该类获取a System.Diagnostics.StackFrame,然后使用该GetMethod()方法获取System.Reflection.MethodBase对象.但是,这种方法有一些注意事项:
(注意:我只是扩展了Firas Assad提供的答案.)
Tik*_*all 56
快速回顾两种方法,速度比较是重要的部分.
在编译时确定调用者
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);
}
Run Code Online (Sandbox Code Playgroud)
使用堆栈确定调用者
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);
}
Run Code Online (Sandbox Code Playgroud)
比较两种方法
Time for 1,000,000 iterations with Attributes: 196 ms
Time for 1,000,000 iterations with StackTrace: 5096 ms
Run Code Online (Sandbox Code Playgroud)
所以你看,使用属性要快得多!事实上快了近25倍.
小智 29
从.NET 4.5开始,您可以使用来电者信息属性:
CallerFilePath - 调用该函数的源文件;CallerLineNumber - 调用函数的代码行; CallerMemberName - 调用该函数的成员.
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);
}
Run Code Online (Sandbox Code Playgroud)
此工具也存在于".NET Core"和".NET Standard"中.
参考
CallerFilePathAttribute班级CallerLineNumberAttribute班级CallerMemberNameAttribute班级显然这是一个迟到的答案,但如果您可以使用.NET 4.5或更高版本,我有更好的选择:
internal static void WriteInformation<T>(string text, [CallerMemberName]string method = "")
{
Console.WriteLine(DateTime.Now.ToString() + " => " + typeof(T).FullName + "." + method + ": " + text);
}
Run Code Online (Sandbox Code Playgroud)
这将打印当前日期和时间,后跟"Namespace.ClassName.MethodName"并以":text"结尾.
样本输出:
6/17/2016 12:41:49 PM => WpfApplication.MainWindow..ctor: MainWindow initialized
Run Code Online (Sandbox Code Playgroud)
样品用途:
Logger.WriteInformation<MainWindow>("MainWindow initialized");
Run Code Online (Sandbox Code Playgroud)
小智 8
/// <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;
}
Run Code Online (Sandbox Code Playgroud)
也许你正在寻找这样的东西:
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
213702 次 |
| 最近记录: |