Я хотел бы создать новый объект 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, и, как я уже упоминал, теряюсь в, казалось бы, бесконечных комбинациях различных конструкторов и методов. Кроме того, меня интересует способ, который также учитывает производительность.
1 ответ
Чтобы построить все по частям, как вы предлагаете, я бы написал что-то вроде приведенного ниже кода. Я также рекомендую вам взглянуть на образец 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());
}
}
Похожие вопросы
Связанные вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.