【发布时间】:2015-03-06 16:30:19
【问题描述】:
我们试图弄清楚如何使用 Roslyn 生成代码。我不是在谈论像 CSharpSyntaxTree.ParseText 这样的东西,它会接受一些字符串并将它们转换为 AST。相反,我想以某种方式构建我的模型(伪代码):
- 创建
file作为编译单元 - 将
MyClass类添加到file - 将方法
DoSomething添加到MyClass - 以类似
System.Linq.Expressions的方式设置DoSomething的主体
我们最近发现了Microsoft.CodeAnalysis.CSharp.SyntaxFactory,它似乎很有希望。但是,显然我们必须自己添加琐事。
在使用SyntaxFactory.CompilationUnit() 构建树并来回添加一些成员之后,ToFullString() 的输出只是一堆文本,既不可读也不可编译(例如,缺少大括号)。从模型生成文本时我们是否遗漏了什么?
编辑:
使用工作区时,您可以设置影响空白行为的选项:
public string Generate (CompilationNode rootNode)
{
var cw = new CustomWorkspace();
cw.Options.WithChangedOption (CSharpFormattingOptions.IndentBraces, true);
var formattedCode = Formatter.Format (CreateFile(rootNode), cw);
return formattedCode.ToFullString();
}
这已经产生了更好的结果。有人可以确认这是一个好的解决方案还是一个 hack?
还有一个问题。我们想生成一个自动属性,目前使用SF.AccessorDeclaration,但在转换为完整字符串时会丢失分号。
【问题讨论】:
-
你的目标是发出代码,对吧?不编译?
-
是的,但没有明确指定琐事。我也有使用 ReSharper SDK 的一些经验,它的应用领域基本相同。他们确实拥有忽略琐事的工厂,并且它确实打印了所有生成的代码,干净且可编译。我遇到了一些建议使用 CodeDOM 的其他用户的 cmet,据说 Roslyn 不适合这个,但这似乎是有史以来最大的失败 :)
-
嗯...作为编译器的 Roslyn 是用来消费代码的,而不是生成代码。
-
对此我不确定。 Roslyn 的构建也是为了在重构等方面支持更好的工具。作为此类重构的作者,我不想处理琐事。正如我所指出的,JetBrains 在那里做得很好。你真的建议说,代码生成最终还是 CodeDOM 和 StringBuilder 的事情吗?似乎不适合我。不要误会我的意思,我会接受这个作为答案,但我仍然宣布这是一个很大的失败。
-
使用格式化程序绝对是一个好方法。如果你想避开 Workspace 层,你也可以使用
SyntaxNode.NormalizeWhitespace()