gpt4 book ai didi

c# - 如何返回 C# 方法调用的语法上下文

转载 作者:行者123 更新时间:2023-12-04 02:28:42 26 4
gpt4 key购买 nike

如果你这样写

this.MyMethod(this.MyMethod(myParam)).Should().BeNull();

使用 FluentAssertions库,当断言失败时抛出异常,并显示消息

Expected this.MyMethod(this.MyMethod(myParam)) to be <null>, but found "foo".

它是如何设法获取方法调用的语法上下文以产生如此有意义的异常消息的?显然使用了某种反射,可能还使用了一些堆栈跟踪检查(实际上,它仅在 Debug模式下以及当表达式写在一行中时才能正常工作),但究竟如何呢?

更具体地说,如何编写带有签名的方法

public static string GetSyntacticContext(object parameter);

满足(在 Debug模式下)以下条件?

GetSyntacticContext("foo")
.Should().Be("\"foo\"");

GetSyntacticContext(myParam + 1)
.Should().Be("myParam + 1");

GetSyntacticContext(this.MyMethod(this.MyMethod(myParam)))
.Should().Be("this.MyMethod(this.MyMethod(myParam))");

最佳答案

您提到它仅在 Debug模式下有效,并且仅当表达式写在一行中时才有效。事实上, Debug模式下的异常堆栈跟踪包含源文件的完整路径和导致异常发生位置的每个堆栈帧的行号。

库因此可以从文件中读取该行并进行检查。它可能会对该行进行完整的表达式解析,但他们更有可能选择使用正则表达式的快捷方式。在您引用的所有示例中,它真正需要做的就是删除 .Should()以及之后的一切。

在您的位置,我会稍微修改源文件(例如,改变间距和/或在行的中间添加一些/* 注释 */)以查看异常消息是否保留了这些。如果是,我们就知道它是从源文件中读取的。如果没有,我敢打赌它仍然从源文件中读取但对相关行执行句法分析并重建它。

您的假设 GetSyntacticContext方法可能会做类似的事情:获取当前堆栈帧及其文件名/行号信息并从文件中读取该行。像这样:

public static string GetSyntacticContext(object parameter)
{
var st = new StackTrace(fNeedFileInfo: true);
var frame = st.GetFrame(1);
return File.ReadLines(frame.GetFileName()).Skip(frame.GetFileLineNumber() - 1).FirstOrDefault();
}

请注意,此示例未使用 parameter范围。在此示例中,我没有尝试检测对 GetSyntacticContext 的调用。并提取方法调用语法中的代码;它只返回整行代码、缩进和所有内容。

顺便说一句,StackFrame类型有一个 GetMethod()方法,因此您可以获得对包含对 GetSyntacticContext 的相关调用的方法的运行时引用.不确定你可以用它做什么,但你可以获得它的 IL 代码,和/或分析 EXE 文件附带的 PDB 文件的内容。不过,这不会真正为您提供实际的 C# 源代码; PDB 文件充其量包含您已有的相同文件名/行号信息,并且它仍然不允许您区分对 GetSyntacticContext 的多次调用。发生在同一语句中。

关于c# - 如何返回 C# 方法调用的语法上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65612045/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com