在C#中是否可以获得当前执行的代码行(不是行号而是代码本身)?

时间:2016-03-04 18:36:20

标签: c# debugging

我想为我的MVC应用程序编写某种调试工具,该工具托管在生产托管环境中,我的访问权限非常有限,无法调试代码,除非将每行代码写入.txt文件。例如,假设我有一个代码:

public void Foo()
{
    var bar = new Bar();
    var baz = new Baz();
    bar.Qux(baz);
}

我现在正在做的是:

public void Foo()
{
    MyTxtDebugger.Write("Enter Foo()")
    MyTxtDebugger.Write("var bar = new Bar();")
    var bar = new Bar();

    MyTxtDebugger.Write("var baz = new Baz();")
    var baz = new Baz();

    MyTxtDebugger.Write("bar.Qux(baz);")
    bar.Qux(baz);

    MyTxtDebugger.Write("Exit Foo()")
}

MyTxtDebugger.Write是我的自定义简单文本编写者。这样做是件事,但我想让代码更清晰,不要将实际代码行复制到字符串。我想要的是:

public void Foo()
{
    [MyTxtDebugger] var bar = new Bar();
    [MyTxtDebugger] var baz = new Baz();
    [MyTxtDebugger] bar.Qux(baz);
}

或者至少这个:

public void Foo()
{
    MyTxtDebugger.Write(); var bar = new Bar();
    MyTxtDebugger.Write(); var baz = new Baz();
    MyTxtDebugger.Write(); bar.Qux(baz);
}

我希望MyTxtDebugger.Write()的输出为"MyTxtDebugger.Write(); var bar = new Bar();"这是可能的,如果可能,怎么做?我已经研究过,例如,this question但是在这种情况下,实际的C#代码没有在输出中捕获。

4 个答案:

答案 0 :(得分:1)

简答:

答案很长:

没有什么可以开箱即用,可以满足您的需求。

您提出的使用[MyTxtDebugger]属性类型的伪代码也不会起作用,因为它不是有效的c#语法。您不能将属性应用于局部变量/语句。

在玩这种魔法时,我会想起PostSharp。它会进行后编译并重写您的IL。 PostSharp Logging会更近,但不完全是你想要的。它可以在您进入/退出某些方法时记录。无法编写正在执行的每个语句。如果你没事,那就去吧。

如果你真的需要你正在寻找的东西,那么我能想到的就是编写你自己的IL织布工。

与Fody相当简单(不那么简单!)看看PropertyChanged.Fody实施情况。它根据所需属性的可用性在编译时实现INPC。

起初PropertyChanged.Fody可能是压倒性的;看看BasicFodyAddin是一个好的开始。

你可以编写自己的fody weaver,查看IL,查找语句,然后发出IL来记录语句。 (如果你这样做,请开源。对其他人真的很有用)

玩得开心。

答案 1 :(得分:0)

考虑到您的评论背景,您的问题的答案

  

这可能,如果可行,怎么办?

否。这是不可能的。

(如果有人证明,我会很乐意删除)

答案 2 :(得分:0)

是可能的。在DEBUG模式下,您可以使用堆栈跟踪提取文件和行信息。这是一个概念证明。

    static void Main(string[] args) {
        ShowCallerLine(); // hello!
        ShowCallerLine(); // goodybye!
    }

    static void ShowCallerLine() {
        var frame = new StackFrame(1, true);
        var lineNumber = frame.GetFileLineNumber();
        var fileName = frame.GetFileName();

        var line = File.ReadLines(fileName).ElementAt(lineNumber - 1);
        Console.WriteLine(line);
    }

<强>输出:

        ShowCallerLine(); // hello!
        ShowCallerLine(); // goodybye!

但是,我建议谨慎使用这样的技术。它很脆弱,容易出现故障和未被发现的行为。

答案 3 :(得分:0)

嗯......我不确切地知道你在找什么,但是如果你正在尝试做记录器已经做的事情,那么你应该看Environment.StackTrace

https://msdn.microsoft.com/en-us/library/system.environment.stacktrace(v=vs.110).aspx

  

FullClassName类的全名,包括命名空间。

     

MethodName方法的名称。

     

MethodParams参数类型/名称对的列表。每一对都是   用逗号分隔(&#34;,&#34;)。如果是MethodName,则省略此信息   没有参数。

     

FileName MethodName方法所在的源文件的名称   声明。如果没有调试符号,则省略此信息   可用。

     

LineNumber FileName中包含源的行号   MethodName中的代码,用于调用堆栈上的指令。   如果调试符号不可用,则省略此信息。

希望这就是你所说的。哦,记得更新Release和Debug构建目标以输出完整调试符号。调试符号是你的朋友。