Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.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#_Roslyn - Fatal编程技术网

C# 如何在编译之前修改代码?

C# 如何在编译之前修改代码?,c#,roslyn,C#,Roslyn,使用Roslyn,我想在实际编译之前修改我的C代码。现在,我只需要以下内容: [MyAnotatedMethod] public void MyMethod() { // method-body } 基于注释,我想在方法的开头和结尾注入一些代码 我知道PostSharp,但那不是我想要的 这可能和Roslyn有关吗?如果是的话,你能给我举个例子吗?这里有一个快速而肮脏的方法来做你想做的事。这是基于上面的评论之一,它指向。这只是一个概念证明,我不会尝试在生产中使用它 基本思想是更改要

使用Roslyn,我想在实际编译之前修改我的C代码。现在,我只需要以下内容:

[MyAnotatedMethod]
public void MyMethod() 
{
    // method-body 
}
基于注释,我想在方法的开头和结尾注入一些代码

我知道PostSharp,但那不是我想要的


这可能和Roslyn有关吗?如果是的话,你能给我举个例子吗?

这里有一个快速而肮脏的方法来做你想做的事。这是基于上面的评论之一,它指向。这只是一个概念证明,我不会尝试在生产中使用它

基本思想是更改要修改的项目的编译器。这个修改过的编译器将执行代码注入。因此,您需要编写一个新的编译器(AopCompiler.exe),并将其设置为项目中的构建工具

将AopCompiler.exe设置为构建工具很容易,在项目文件中,需要添加以下两行:

<CscToolPath>$(SolutionDir)AopCompiler\bin\Debug</CscToolPath>
<CscToolExe>AopCompiler.exe</CscToolExe>
因此,如果您设置到目前为止,您将有一个正常的构建过程,没有方面编织

此时,如果您查看
args
中的内容,您将看到.RSP文件的文件路径,其中包含csc.exe的所有命令行参数。当然,这些参数也包含所有的.CS文件名。因此,您可以解析这个.RSP文件并找到编译过程中的所有.CS文件

有了手中的C#文件,可以用Roslyn完成重写。例如,
CSharpSyntaxRewriter
上有许多教程,以及。您需要编写自定义的
CSharpSyntaxRewriter
,它检查给定的属性,然后将日志添加到找到的方法的开头。在每个方法的末尾添加日志记录有点棘手,因为可能有多个退出点。要找到这些,可以使用控制流分析。内置的Roslyn控件流分析可以为您提供所需的内容,该属性保存区域内的一组语句,这些语句跳转到区域外的位置

要获取语义模型(然后进行CFG分析),可以执行以下操作:

public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
{
    var semanticModel = _compilation.GetSemanticModel(node.SyntaxTree);
    // semanticModel.AnalyzeControlFlow(node.Block)
    return node;
}
最后,要处理每个输入文件,即AOP编译器,只需调用树根上重写器的
Visit
方法即可。这将生成修改后的树,您可以将其写入文件。(您可以修改原始文件,也可以将结果写入新文件,并相应地更改.RSP文件。)


很抱歉没有提供完整的工作解决方案,但我希望,这足以让您开始。

正如我在评论中指出的,目前还没有。尽管您可以使用中显示的AOP技术将某些内容组合在一起,以提供非常灵活的解决方案

此时的正确答案是Roslyn团队有一个开放的提案/问题来支持它。感谢.NET基金会和微软参与开源,您可以在这里阅读关于这个特性的开发:


这比使用注释稍微脏一点,但使用预处理器指令阻止代码将允许您配置代码如何基于标志编译

只有在定义了MyFlag的情况下,才会编译下面的#ifMyFlag中的代码

#define MyFlag
public void MyMethod() 
{
    #if MyFlag
        // Flag conditional code

    #endif

    // method-body 
}

这不是你想要达到的吗?它的基本思想是使用一个独立的可执行文件进行修改和编译,并将该可执行文件添加为构建工具。我喜欢这样的问题,一方面,你有一个传说说,
Roslyn团队说他们将支持代码注入,可能不是第一个版本
@Bjørn Roger Kringsjå能否请您说明您希望Roslyn如何以与正常实现不同的方式实现此功能:@Jeremythonpson为什么我要指出任何事情?我看到一个有趣的问题,就悬赏。如果你有答案,请将其作为答案发布。顺便说一句,如果你能证明/记录这是不可能的,这是一个可以接受的答案。好答案-我记得很久以前在一个项目中使用If条件下的静态函数调用做过这件事。与属性相比,它没有太多额外的工作,而且比AOP方法更容易实现。
元素下面的-Element是未知的
。正如您所看到的,我已经在
项目
元素末尾的
.csproj
文件中插入了您的两行代码。这里怎么了?
#define MyFlag
public void MyMethod() 
{
    #if MyFlag
        // Flag conditional code

    #endif

    // method-body 
}