如何在编译之前修改代码? [英] How to modify code before compilation?

查看:178
本文介绍了如何在编译之前修改代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用罗斯林,我想实际编译之前修改我的C#代码。现在,我只是需要一些这样的:

Using Roslyn, I would like to modify my C# code before the actual compilation. For now, I will just need something like:

[MyAnotatedMethod]
public void MyMethod() 
{
    // method-body 
}

和基于注解,我想在方法的开始注入一些代码,并在方法结束。

And based on the annotation, I would like to inject some code at the beginning of the method, and at the end of the method.

我知道PostSharp的,但是这不是我愿意喜欢。

I'm aware of PostSharp, but that's not what I would like.

这是可以做到与罗斯林?如果是,你能不能举个例子?

Is this possible to do with Roslyn? And if yes, could you give me an example?

推荐答案

下面是做你想要什么样的一个快速和肮脏的方式。它基于上述意见,指向 SebbyLive 之一。这只是一个概念证明,我不会试图在生产中使用它。

Here is a quick and dirty way of doing what you want. It's based on one of the above comments, which points to SebbyLive. It is just a proof of concept, I wouldn't try to use it in production.

其基本思想是,你改变你要修改的项目的编译器。而这种变化的编译器会做的代码注入。所以,你需要写一个新的编译器(AopCompiler.exe)并将它设置为你的项目构建工具。

The basic idea is that you change the compiler of the project that you want to modify. And this changed compiler will do the code injection. So you'd need to write a new compiler (AopCompiler.exe) and set it as the build tool in your project.

设置AopCompiler.exe作为构建工具很简单,在你的项目文件,你需要添加以下两行:

Setting the AopCompiler.exe as the build tool is easy, in you project file, you'd need to add the following two lines:

<CscToolPath>$(SolutionDir)AopCompiler\bin\Debug</CscToolPath>
<CscToolExe>AopCompiler.exe</CscToolExe>



AopCompiler应该是一个简单的控制台应用程序。这是做的代码修改和编译了。
如果你不想修改源代码,就建立它,那么最简单的方法是调用CSC.EXE自己:

The AopCompiler should be a simple console application. This is doing the code modification and the compilation too. If you don't want to modify the source code, just build it, then the easiest way is to call the csc.exe yourself:

static void Main(string[] args)
{
  var p = Process.Start(@"C:\Program Files (x86)\MSBuild\14.0\Bin\csc.exe", 
            string.Join(" ", args));
  p.WaitForExit();
}



所以,如果你设置此到目前为止你有一个正常的构建过程未经纵横编织。

So if you set this up so far you'd have a normal build process, without the aspect weaving.

在这一点上,如果你看看什么是在 ARGS ,你会看到有一个文件路径的.RSP文件,它包含了所有的CSC.EXE命令行参数。当然,这些参数包含所有的.CS文件名了。所以,你可以分析这个.RSP文件,并找到所有的.CS文件,是编译的一部分。

At this point, if you check out what is in the args, you'll see that there is a file path to an .RSP file, which contains all the command line parameters for the csc.exe. Naturally, these parameters contain all the the .CS file names too. So you could parse this .RSP file and find all the .CS files, that are part of the compilation.

在手的C#文件,重写可以与罗斯林完成。有关于 CSharpSyntaxRewriter 很多教程,例如的这里,这里 。你需要编写自定义 CSharpSyntaxRewriter ,它检查给定的属性,然后记录添加到的发现方法的开始。添加记录到每个方法的到底是有点棘手,因为可以有多个出口点。为了找到这些,你还可以使用控制流分析。内置的罗斯林控制流分析可以给你,你是什么之后, ExitPoints 属性保存设定的区域内语句跳转到区域外的位置。

With the C# files in hand, the rewriting can be done with Roslyn. There are many tutorials on CSharpSyntaxRewriter, for example here, and here. You'd need to write your custom CSharpSyntaxRewriter, which checks for the given attribute, and then add the logging to the beginning of the found methods. Adding logging to the end of each method is a bit trickier, because there can be multiple exit points. To find those, you can use control flow analysis. The built-in Roslyn control flow analysis can give you exactly what you are after, the ExitPoints property holds the set of statements inside a region that jump to locations outside the region.

要获得语义模型(然后做CFG分析),你可以做这样的事情:

To get the semantic model (and then do the CFG analysis) you can do something like this:

public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
{
    var semanticModel = _compilation.GetSemanticModel(node.SyntaxTree);
    // semanticModel.AnalyzeControlFlow(node.Block)
    return node;
}



最后,为了处理每个输入文件,你的AopCompiler,你只是简单地要叫你重写的访问方法对树的根。这会产生修改后的树,你可以写出来的文件。 (要么你可以修改原文件,或将结果写到一个新的,并相应地更改.RSP文件。)

Finally, to process each of the input files, your AopCompiler, you just simply have to call your rewriter's Visit method on the root of the tree. That will produce the modified tree, which you can write out to a file. (Either you can modify the original file, or write the result to a new one, and change the .RSP file accordingly.)

对不起,不提供全面有效的解决方案,但我希望,这足以让你开始。

Sorry for not providing a full working solution, but I hope, this is enough to get you started.

这篇关于如何在编译之前修改代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆