获取运行时类型的堆栈帧

时间:2014-06-02 08:31:13

标签: c# .net stack-trace callstack

我想知道是否有可能在堆栈跟踪中获取运行时类型的方法调用方。

考虑以下示例:

class Parent
{
    public void Foo()
    {
        var stack = new StackTrace();

        foreach (var frame in stack.GetFrames())
        {
            var methodInfo = frame.GetMethod();
            Console.WriteLine("{0} (ReflectedType: {1})", methodInfo.ToString(), methodInfo.DeclaringType);
        }
    }
}

class Child : Parent
{
}

如果我创建Child的实例并调用Foo

var child = new Child();
child.Foo();

Foo将打印: Void Foo()(ReflectedType:Parent)

有没有办法在堆栈跟踪中获取方法调用者的实际运行时类型(在本例中为Child)?

2 个答案:

答案 0 :(得分:2)

没有。原因由Raymond Chen here描述。

相关引用是:

  

在执行其调用的函数期间,代码块中的对象可以符合收集条件。

这不直观,请阅读有关JIT和GC协同工作的部分。

获取实际类型需要实例,但优化工作是为了制作垃圾,所以你不能依赖它仍然在那里。

答案 1 :(得分:0)

您正在致电Parent.Foo(),这就是您获得Parent类型的原因。

一种方法是在Child中创建一个方法:

class Parent
{
}

class Child : Parent
{
    public void Foo()
    {
        var stack = new StackTrace();
        foreach (var frame in stack.GetFrames())
        {
            var methodInfo = frame.GetMethod();
            Console.WriteLine("{0} (ReflectedType: {1})", methodInfo.ToString(), methodInfo.DeclaringType);
        }
    }
}

Proof

但我能想到的是用法。你打算在哪里获得有关堆栈,类型,方法的信息?更有可能在某些记录器中。然后你真的不需要知道它是Parent.Foo()还是Child.Foo(),因为你(作为程序员)确定Foo()在哪里。

其他事情就是(仅对记录器)只知道调用者就足够了,那就像

一样简单
public static void Log(string message, Exception exception = null)
{
    var method = new StackFrame(1).GetMethod();
    // get caller name, so that you don't need to specify it, when calling Log()
    var caller = method.DeclaringType.Name + "." + method.Name;
    ...
}