2

我想使用以下类作为具体示例逐步构建一个新的 IDocument 对象。您可以从您喜欢的任何对象开始并使用您喜欢的任何中间对象,只要生成的对象是最后代表完整类的 IDocument。

第 1 步:添加一个名为 MyNamespace 的新命名空间。此时打印出当前对象应如下所示:

namespace MyNamespace
{
}

步骤#2:向这个命名空间添加一个名为 MyClass 的新类。此时打印出当前对象应如下所示:

namespace MyNamespace
{
    public class MyClass
    {
    }
}

步骤#3:向这个类添加一个名为 MyMethod 的新方法。此时打印出当前对象应如下所示:

namespace MyNamespace
    {
        public class MyClass
        {
            public void MyMethod()
            {
            }
        }
    }

我遇到的问题是,理论上你可以用无数种方法来解决这个问题,或者至少错误地认为你可以解决这个问题。各种不同对象(如 WithChanges、UpdateDocument、各种 Syntax 对象上的方法、ParseCompilationUnit 等)中的无尽方法和构造函数。

基本上,我想以增量方式构建它,每一步都有一个不同的对象,例如我可以打印到控制台,而不是一个大语句在一行中创建整个事情。我已经多次阅读 CTP 6 月版本附带的所有文档,正如我所提到的,我迷失在看似无穷无尽的各种构造函数和方法的组合中。此外,我对一种也考虑性能的方式感兴趣。

4

1 回答 1

5

要按照您的建议逐步构建所有内容,我会编写类似于下面的代码的内容。我还鼓励您查看 ImplementINotifyPropertyChanged 示例,因为它进行了大量的语法构造和重写。请注意,正如您所建议的,您可以通过多种方式执行此操作。这是因为 API 旨在支持编辑器等场景,因此您也可以通过为用户键入的每次击键应用文本更改来构建它。哪个 API 是正确的取决于您要实现的目标。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;
using Roslyn.Services;
using Roslyn.Services.CSharp;

class Program
{
    static void Main(string[] args)
    {
        // Create the solution with an empty document
        ProjectId projectId;
        DocumentId documentId;
        var solution = Solution.Create(SolutionId.CreateNewId())
            .AddProject("MyProject", "MyProject", LanguageNames.CSharp, out projectId)
            .AddDocument(projectId, @"C:\file.cs", string.Empty, out documentId);

        var document = solution.GetDocument(documentId);
        var root = (CompilationUnitSyntax)document.GetSyntaxRoot();

        // Add the namespace
        var namespaceAnnotation = new SyntaxAnnotation();
        root = root.WithMembers(
            Syntax.NamespaceDeclaration(
                Syntax.ParseName("MyNamespace"))
                    .NormalizeWhitespace()
                    .WithAdditionalAnnotations(namespaceAnnotation));
        document = document.UpdateSyntaxRoot(root);

        Console.WriteLine("-------------------");
        Console.WriteLine("With Namespace");
        Console.WriteLine(document.GetText().GetText());

        // Find our namespace, add a class to it, and update the document
        var namespaceNode = (NamespaceDeclarationSyntax)root
            .GetAnnotatedNodesAndTokens(namespaceAnnotation)
            .Single()
            .AsNode();

        var classAnnotation = new SyntaxAnnotation();
        var newNamespaceNode = namespaceNode
            .WithMembers(
                Syntax.List<MemberDeclarationSyntax>(
                    Syntax.ClassDeclaration("MyClass")
                        .WithAdditionalAnnotations(classAnnotation)));
        root = root.ReplaceNode(namespaceNode, newNamespaceNode).NormalizeWhitespace();
        document = document.UpdateSyntaxRoot(root);

        Console.WriteLine("-------------------");
        Console.WriteLine("With Class");
        Console.WriteLine(document.GetText().GetText());

        // Find the class, add a method to it and update the document
        var classNode = (ClassDeclarationSyntax)root
            .GetAnnotatedNodesAndTokens(classAnnotation)
            .Single()
            .AsNode();
        var newClassNode = classNode
            .WithMembers(
                Syntax.List<MemberDeclarationSyntax>(
                    Syntax.MethodDeclaration(
                        Syntax.ParseTypeName("void"),
                        "MyMethod")
                        .WithBody(
                            Syntax.Block())));
        root = root.ReplaceNode(classNode, newClassNode).NormalizeWhitespace();
        document = document.UpdateSyntaxRoot(root);

        Console.WriteLine("-------------------");
        Console.WriteLine("With Method");
        Console.WriteLine(document.GetText().GetText());
    }
}
于 2012-06-24T05:10:17.313 回答