我需要能够获得已被调用到某一点的所有方法的列表。不幸的是,我无法使用CallerInformation属性,因此几乎只留下了StackTrace。
我知道StackTrace对于性能不是很好,所以我希望有其他替代方案可以做到这一点而不是性能太重。我发现这篇文章(https://ayende.com/blog/3879/reducing-the-cost-of-getting-a-stack-trace)有一个如何加速堆栈跟踪的例子,但我不确定如何使用它来真正获得方法名称。这就是我到目前为止所拥有的:
void Main()
{
var result = getTheStackTrace.Invoke();
}
private Func<object> getTheStackTrace;
public void FastStack()
{
var stackFrameHelperType = typeof(object).Assembly.GetType("System.Diagnostics.StackFrameHelper");
var GetStackFramesInternal = Type.GetType("System.Diagnostics.StackTrace, mscorlib").GetMethod("GetStackFramesInternal", BindingFlags.Static | BindingFlags.NonPublic);
var method = new DynamicMethod("GetStackTraceFast", typeof(object), new Type[0], typeof(StackTrace), true);
var generator = method.GetILGenerator();
generator.DeclareLocal(stackFrameHelperType);
generator.Emit(OpCodes.Ldc_I4_0);
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Newobj, stackFrameHelperType.GetConstructor(new[] { typeof(bool), typeof(Thread) }));
generator.Emit(OpCodes.Stloc_0);
generator.Emit(OpCodes.Ldloc_0);
generator.Emit(OpCodes.Ldc_I4_0);
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Call, GetStackFramesInternal);
generator.Emit(OpCodes.Ldloc_0);
generator.Emit(OpCodes.Ret);
getTheStackTrace = (Func<object>)method.CreateDelegate(typeof(Func<object>));
}
如何从调用getTheStackTrace.Invoke()
来获取方法的名称我对如何获取信息感到有些困惑。任何帮助,将不胜感激。感谢。
答案 0 :(得分:0)
我实际上在StackFrameHelper类中构建了类似于该示例所示的类似内容。除了我使用缓存/编译的表达式树来调用函数而不是IL,因为你需要调用大约5或6个方法而且一切都是内部/私有的。由于版权问题,无法发布课程,但我至少可以指出您正确的方向。您需要新建一个StackFrameHelper实例,然后调用GetStackFramesInternal,然后调用GetNumberOfFrames,然后为每个帧调用GetMethodBase,如果需要该信息,可以调用GetFileName和GetLineNumber。
除了StackFrame类上的GetStackFramesInternal之外,所有这些方法都在StackFrameHelper类上。
上面的代码只是转到GetStackFramesInternal级别,它填充了StackFrameHelper实例。