我想在调用函数时传递一个值,但想省略实际添加它作为参数。
更准确地说,我想编写一个记录器,它也会打印出哪个类称为记录功能但不想总是将“this”作为参数传递。
示例代码:
class static Logger{
public static void LogMsg(string msg, object objectCalling){
Print(objectCalling.GetType().Name + ": " + msg);
}
private void Print(string msg){
// print it
}
}
class SomeClass{
private void WriteTestLog() {
Logger.LogMsg("Testing!");
}
}
然后应该创建一个输出,如:“SomeClass:Testing!”
我不知道如何解决这个问题,也许我只是错过了......
答案 0 :(得分:2)
有一些属性可能会有所帮助:
CallerMemberNameAttribute
:调用方法或属性的名称; CallerFilePathAttribute
:调用成员所在的文件路径; CallerLineNumberAttribute
:文件中的行号。如您所见,类名没有属性,但使用文件路径可能会获得相同级别的信息。
如何使用这个?使用属性(当然,使用正确的类型和默认值)在日志记录方法中装饰一个参数。
public static void LogMsg(string msg, [CallerMemberName] string callingMember = null)
{
Print($"{callingMember}: {msg}");
}
然后致电:
LogMsg("hello!");
答案 1 :(得分:2)
您可以System.Runtime.CompilerServices
使用CallerMemberNameAttribute
以下是示例:
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
Logger.WriteLog("Hello");
}
}
public class Logger
{
public static void WriteLog(string msg, [CallerMemberName] string methodName="")
{
Console.WriteLine("Method:{0}, Message: {1}",methodName,msg);
}
}
}
答案 2 :(得分:0)
您可以创建一个扩展方法来执行此操作以及上面的答案:
void Main()
{
SomeClass x = new SomeClass();
x.WriteTestLog();
int i = 1;
i.LogMsg("abc");
}
public static class Logger
{
public static void LogMsg(this object objectCalling, string msg)
{
Print(objectCalling.GetType().Name + ": " + msg);
}
private static void Print(string msg)
{
Console.WriteLine(msg); // print it
}
}
public class SomeClass
{
public void WriteTestLog()
{
this.LogMsg("Testing!");
}
}
答案 3 :(得分:0)
如果你真的希望提取调用者的类型,你可以使用堆栈跟踪:
[MethodImpl(MethodImplOptions.NoInlining)]
public static void LogMsg(string msg)
{
var caller = new StackTrace().GetFrames()[1].GetMethod();
Console.WriteLine($"{caller.DeclaringType}.{caller.Name}: {msg}");
}
但请记住,从堆栈跟踪中提取调用方是一项非常昂贵的操作。除了NoInlining
之外,不能保证在优化的构建中,调用者本身不会内联。我不建议在发布版本中使用它,或者如果性能很重要。