我可以更改C#中的当前堆栈跟踪吗?

总之,我需要修改C#中的当前堆栈跟踪,以便我调用的方法(我无法修改)会认为它是其他人调用它的方法。

现在,为了说明为什么我需要做这样一个可怕的黑客行为。

在Unity3d中,Debug.Log在开发人员控制台中创建一条新记录。 当你双击它时,它会打开IDE显示对该记录负责的确切文件和行。 但是,由于各种原因(禁用生产中的调试,使其可用于其他线程)我创建了一个包装类Print ,而不是UnityEngine.Debug。

但是对于包装器,现在当开发人员在控制台中单击日志记录时,打开的是Print ,而不是调用Print.Log的实际位置。 而且由于Debug.Log不管错误消息或上下文对象如何执行,我都认为它使用调用堆栈来标识要打开的文件。 不用说,我想解决这个问题。


我不相信这是可能的。 查看Environment.StackTrace的源代码和后续的GetStackTrace()调用,我们可以看到它每次调用时都会创建堆栈跟踪。 由于似乎没有什么可以注入来改变它的某些工作,所以我认为可以断定,如果不修改它的调用方式,就不能更改堆栈跟踪。

如果你有可能做到这一点,你可以使用类似这样的东西来检索当前的StackFrame并使用反射来改变最近的StackFramemethod字段,以模仿你正在做什么。

void Main()
{
    DoSomething();
}

void DoSomething(){
    Console.WriteLine (Environment.StackTrace); // Last frame: at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)

    var frames = new StackTrace().GetFrames();
    var lastframe = frames[0]; // last frame: DoSomething at offset 100 in file:line:column <filename unknown>:0:0
    var methodField = lastframe.GetType().GetField("method", BindingFlags.Instance | BindingFlags.NonPublic);
    var redirectedMethod = typeof(Redirect).GetMethod("RedirectToMethod", BindingFlags.Instance | BindingFlags.Public);
    methodField.SetValue(lastframe, redirectedMethod);
    Console.WriteLine (frames); // last frame: RedirectToMethod at offset 100 in file:line:column <filename unknown>:0:0
    Console.WriteLine (Environment.StackTrace); // last frame: at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
}

public class Redirect {
    public void RedirectToMethod() { }
}

但是,再一次:这是非常脆弱的,不适用于你目前的情况。 你试图做的是相当奇特的,应该完全避免。

至于实际的解决方案:恐怕我没有任何Unity经验,所以我只能谷歌,但这个线程可能会让你感兴趣。 我在这里提到了.NET源代码,但你可以在Mono源程序中找到非常类似的代码。


一个解决这个问题的方法是将你的Print类编译成一个兼容的Dll(我认为.Net 2)。 当双击日志时,控制台将忽略dll信息并转到Print调用的位置。

链接地址: http://www.djcxy.com/p/80819.html

上一篇: Can I change current stacktrace in C#?

下一篇: SSH suddenly asking for password