如何获取调用我的方法的类名? [复制]

Posted

技术标签:

【中文标题】如何获取调用我的方法的类名? [复制]【英文标题】:How to get Class name that is calling my method? [duplicate] 【发布时间】:2018-07-12 05:45:30 【问题描述】:

我想编写自己的记录器。

这是我的记录器管理员:

public static class LoggerManager

    public static void Error(string name)
    

    

我正在调用Error(string name);方法如下:

public class Foo

    public void Test()
    
        LoggerManager.Error(this.GetType().FullName);
    

通过这种方式,我在名为Error 的方法中获取调用者类名。

但我不想每次都将名称传递给错误方法。我想让我的记录器(或其他记录器方法:Info()Warn())方法自己获取名称。

感谢您的最佳实践...

【问题讨论】:

查看副本,但不是调用.Name 而是调用.DeclaringType 来获取Type 实例,然后您可以获得名称、全名、程序集信息等等。 我投票重开这个问题。 OP想要获取调用者类而不是方法。 但是你可以很容易地得到定义方法的类,不是吗?如果我们重新打开这个问题,人们可能还会问如何获取命名空间或如何获取定义属性的类。只是因为这个问题不适合确切的用例,它才能回答这个问题。 @HimBromBeere,我不同意你的看法。当然,我们可以通过引用的问题轻松获取类名,但是关于获取类名的问题非常清楚。无论如何,引用的答案并不适合确切的答案。 重点是,如果我们正在寻找 exactly 匹配上下文的重复项,那么我们不太可能找到 any 重复项,因为上下文可能与副本中的内容略有不同。 【参考方案1】:

您可以使用CallerMemberNameCallerFilePath 属性

public static void Log(string text, [CallerMemberName] string caller = "", [CallerFilePath] string file = "")

   WriteLog(text, caller, file);



Log("Something happened");

另见CallerLineNumber


顺便说一句:您可能希望将昂贵的 StackFrame 的速度与内置属性进行比较。

int num = 500000;
var t1 = Measure(() => NameOfCallingClass(), num); //<-- 9000
var t2 = Measure(() => Log("aa"), num); //<--26


long Measure(Action func, int num)

    func();
    var sw = Stopwatch.StartNew();
    for (int i = 0; i < num; i++)
    
        func();
    
    return sw.ElapsedMilliseconds;

【讨论】:

来电者信息属性不回答问题。他想要类名,而不是成员名或驻留类的文件路径。使用 stackframe voodoo 是目前唯一已知的方法。此外,使用 [CallerFilePath] 将获取文件编译时的路径。总而言之,在生产日志中这看起来像垃圾。 类似 csproj 中的 $(SolutionDir)=.\ 的东西修复了 Oyvind 的最后一个反对意见。 string callerClassName = Path.GetFileNameWithoutExtension(callerFilePath); 将适用于类名,假设文件名对应于包含的类名。【参考方案2】:

你可以使用System.Diagnostics的StackFrame和System.Reflection的MethodBase。

StackFrame(Int32, Boolean) 初始化StackFrame 类的新实例,该实例对应于当前堆栈帧上方的帧,可选择捕获源信息。

MethodBase,提供有关方法和构造函数的信息。

public static string NameOfCallingClass()

    string fullName;
    Type declaringType;
    int skipFrames = 2;
    do
    
        MethodBase method = new StackFrame(skipFrames, false).GetMethod();
        declaringType = method.DeclaringType;
        if (declaringType == null)
        
            return method.Name;
        
        skipFrames++;
        fullName = declaringType.FullName;
    
    while (declaringType.Module.Name.Equals("mscorlib.dll", StringComparison.OrdinalIgnoreCase));

    return fullName;

您的记录器类调用此方法:

public static void Error()

    string name = NameOfCallingClass();

【讨论】:

谢谢你。这看起来处理的不仅仅是获取 Method.DeclaringType - 您能否添加一些解释,说明为什么需要 While 循环以及为什么需要检查“mscorlib.dll”? 在 C# 聊天中,@TomW 提供了帮助:declaringType = method.DeclaringType 获得了类名。 while 循环通过递增skipFrames 来查找堆栈,查找调用类型不在mscorlib.dll 中的第一帧。换句话说,它不是 Microsoft 课程,而是您自己的课程。【参考方案3】:

您可以从 StackTrace 实例中获取它。

public static class LoggerManager

    public static void Error()
    
        var methodInfo = new StackTrace().GetFrame(1).GetMethod();
        var clasName = methodInfo.ReflectedType.Name;
    

【讨论】:

GetFrame(1) 返回 LoggerManager 。 GetFrame(2) 返回 Foo 。 @kabul 想得到Foo

以上是关于如何获取调用我的方法的类名? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

C# - 调用异常时如何获取类名和行号

附加属性时如何获取类名? [复制]

如何在 Angular 中获取数据模型的类名? [复制]

如何获取包中的所有类名? [复制]

如何在 Swift 上打印类名? [复制]

如何确定调用方法和类名? [复制]