我想知道是否有可能在堆栈跟踪中获取运行时类型的方法调用方。
考虑以下示例:
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)?
答案 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);
}
}
}
但我能想到的是用法。你打算在哪里获得有关堆栈,类型,方法的信息?更有可能在某些记录器中。然后你真的不需要知道它是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;
...
}