自动将自己的类型传递给函数调用

时间:2017-07-07 13:38:08

标签: c# reflection

我想在调用函数时传递一个值,但想省略实际添加它作为参数。

更准确地说,我想编写一个记录器,它也会打印出哪个类称为记录功能但不想总是将“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!”

我不知道如何解决这个问题,也许我只是错过了......

4 个答案:

答案 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之外,不能保证在优化的构建中,调用者本身不会内联。我不建议在发布版本中使用它,或者如果性能很重要。