Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以在C#中更改当前堆栈跟踪吗?_C#_Mono_Unity3d - Fatal编程技术网

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

我可以在C#中更改当前堆栈跟踪吗?,c#,mono,unity3d,C#,Mono,Unity3d,简而言之,我需要修改C#中的当前堆栈跟踪,这样我调用的方法(我无法修改)会认为是其他人调用了它 现在,给一个小的背景,为什么我需要做这样一个可怕的黑客 在Unity3d中,在开发人员控制台中创建新记录。当您双击它时,它会打开IDE以显示负责该记录的确切文件和行。然而,由于各种原因(在生产中禁用调试,使其在其他线程中可用),我创建了一个包装类Print,我使用它代替UnityEngine.debug 但是使用wrapper,现在当开发人员在控制台中单击日志记录时,打开的是Print,而不是调用Pr

简而言之,我需要修改C#中的当前堆栈跟踪,这样我调用的方法(我无法修改)会认为是其他人调用了它

现在,给一个小的背景,为什么我需要做这样一个可怕的黑客

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


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

我认为这是不可能的。查看的源代码和后续调用,我们可以在每次调用时看到它。由于似乎没有任何东西可以注入来改变它的某些工作方式,因此我认为可以得出这样的结论:如果不修改stacktrace的调用方式,就无法更改它

如果您有可能这样做,您可以使用类似这样的方法来检索当前stacktrace,并使用反射来更改最近的
方法
字段,以模拟您所追求的内容

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() { }
}
void Main()
{
DoSomething();
}
无效剂量测定法(){
Console.WriteLine(Environment.StackTrace);//最后一帧:在System.Environment.GetStackTrace(异常e,布尔needFileInfo)
var frames=new StackTrace().GetFrames();
var lastframe=frames[0];//最后一帧:文件:行:列:0:0中偏移量为100的DoSomething
var methodField=lastframe.GetType().GetField(“方法”,BindingFlags.Instance | BindingFlags.NonPublic);
var redirectedMethod=typeof(Redirect).GetMethod(“RedirectToMethod”,BindingFlags.Instance | BindingFlags.Public);
设置值(lastframe,redirectedMethod);
Console.WriteLine(frames);//文件:行:列:0:0中偏移量为100的最后一帧:重定向到方法
Console.WriteLine(Environment.StackTrace);//最后一帧:在System.Environment.GetStackTrace(异常e,布尔needFileInfo)
}
公共类重定向{
public void RedirectToMethod(){}
}
但再一次:这是非常脆弱的,不适用于你目前的情况。你正在尝试做的事情是相当奇特的,应该完全避免


至于一个实际的解决方案:恐怕我对Unity没有任何经验,所以我只能用谷歌搜索,但你可能会感兴趣。我在这里提到了.NET源代码,但您可以在Mono源代码中找到。

解决方法是将您的Print类编译成与unity兼容的Dll(.NET 2)。双击日志时,控制台将忽略dll信息并转到调用Print的位置

我理解你这么做的动机。我认为这是不可能的,因为这将使规避任何代码访问安全概念成为可能,我也这么认为,但我必须要求确保。找到此链接,建议将调试类移动到其他程序集。@SirBraneDamuj我可以确认此建议有效,我的记录器就是这样工作的。