我们试图找出如何使用Roslyn生成代码。我不会谈论像CSharpSyntaxTree.ParseText
这样的东西,它会占用一些字符串并将它们转换成AST。相反,我想以某种方式构建我的模型(伪代码):
file
作为编译单元MyClass
添加到file
DoSomething
添加到MyClass
DoSomething
System.Linq.Expressions
的正文
醇>
我们最近发现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();
}
这已经产生了更好的结果。有人可以证实这是一个很好的解决方案,还是一个黑客?
还有一个问题。我们想要生成一个自动属性,目前使用SF.AccessorDeclaration
,但在转换为完整字符串时它会错过分号。
答案 0 :(得分:10)
你基本上必须添加块定义,然后只要你使用Formatter(就像你写的那样),Roslyn就会为你处理这个琐事
这是一个正确生成的简单类的示例,无需我自己指定任何琐事
var consoleWriteLine = Syntax.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
Syntax.IdentifierName("Console"),
name: Syntax.IdentifierName("WriteLine"));
var arguments = Syntax.ArgumentList (
Syntax.SeparatedList (
new[]
{
Syntax.Argument (
Syntax.LiteralExpression (
SyntaxKind.StringLiteralExpression,
Syntax.Literal (@"""Goodbye everyone!""", "Goodbye everyone!")))
}));
var consoleWriteLineStatement = Syntax.ExpressionStatement (Syntax.InvocationExpression (consoleWriteLine, arguments));
var voidType = Syntax.ParseTypeName ("void");
var method = Syntax.MethodDeclaration (voidType, "Method").WithBody (Syntax.Block(consoleWriteLineStatement));
var intType = Syntax.ParseTypeName ("int");
var getterBody = Syntax.ReturnStatement (Syntax.DefaultExpression (intType));
var getter = Syntax.AccessorDeclaration (SyntaxKind.GetAccessorDeclaration, Syntax.Block (getterBody));
var property = Syntax.PropertyDeclaration (intType, "Property").WithAccessorList (Syntax.AccessorList (Syntax.SingletonList (getter)));
var @class = Syntax.ClassDeclaration ("MyClass").WithMembers (Syntax.List (new MemberDeclarationSyntax[] { method, property }));
var cw = new CustomWorkspace();
cw.Options.WithChangedOption (CSharpFormattingOptions.IndentBraces, true);
var formattedCode = Formatter.Format (@class, cw);
Console.WriteLine (formattedCode.ToFullString());
注意:语法= Microsoft.CodeAnalysis.CSharp.SyntaxFactory
这将生成以下类定义:
class MyClass
{
void Method()
{
Console.WriteLine("Goodbye everyone!");
}
int Property
{
get
{
return default(int);
}
}
}
似乎很好。
答案 1 :(得分:0)
我遇到了同样的问题,发现 CustomWorkspace 现在称为 AdhocWorkspace 。
var cw = new AdhocWorkspace();
cw.Options.WithChangedOption(CSharpFormattingOptions.IndentBraces, true);
var formatter = Formatter.Format(cu, cw);
StringBuilder sb = new StringBuilder();
using (StringWriter writer = new StringWriter(sb))
{
formatter.WriteTo(writer);
}
var code = sb.ToString();