C#Roslyn API,读取一个.cs文件,更新一个类,写回.cs文件

本文关键字:一个 cs 文件 写回 更新 读取 C#Roslyn API | 更新日期: 2023-09-27 18:28:07

我有一个工作代码,它将把一个.cs文件加载到Roslyn SyntaxTree类中,创建一个新的PropertyDeclarationSyntax,插入该类中,然后重写该.cs文件。我这样做是一种学习体验,也是一些潜在的未来想法。我发现任何地方似乎都没有完整的Roslyn API文档,我不确定我是否能有效地完成这项工作。我主要关心的是在哪里调用"root.ToFullString()"——虽然它有效,但这是正确的方法吗?

using System.IO;
using System.Linq;
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;
class RoslynWrite
{
    public RoslynWrite()
    {
        const string csFile = "MyClass.cs";
        // Parse .cs file using Roslyn SyntaxTree
        var syntaxTree = SyntaxTree.ParseFile(csFile);
        var root = syntaxTree.GetRoot();
        // Get the first class from the syntax tree
        var myClass = root.DescendantNodes().OfType<ClassDeclarationSyntax>().First();
        // Create a new property : 'public bool MyProperty { get; set; }'
        var myProperty = Syntax.PropertyDeclaration(Syntax.ParseTypeName("bool"), "MyProperty")
                            .WithModifiers(Syntax.Token(SyntaxKind.PublicKeyword))
                            .WithAccessorList(
                            Syntax.AccessorList(Syntax.List(
                                Syntax.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                                    .WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)),
                                Syntax.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                                    .WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)))));
        // Add the new property to the class
        var updatedClass = myClass.AddMembers(myProperty);
        // Update the SyntaxTree and normalize whitespace 
        var updatedRoot = root.ReplaceNode(myClass, updatedClass).NormalizeWhitespace();
        // Is this the way to write the syntax tree? ToFullString?
        File.WriteAllText(csFile, updatedRoot.ToFullString());
    }
}

C#Roslyn API,读取一个.cs文件,更新一个类,写回.cs文件

在Roslyn CTP论坛上回答了这篇文章:

这种方法通常很好,但如果您担心为整个文件的文本分配字符串,则可能应该使用IText.Write(TextWriter)而不是ToFullString()。

请记住,可以生成不会在解析器中往返的树。例如,如果您生成了违反优先级规则的内容,SyntaxTree构造API将无法捕捉到。