Я изучаю использование компилятора Roslyn в Visual Studio Extension (VSIX), который использует VisualStudioWorkspace для обновления существующего кода. Проведя последние несколько дней, прочитав об этом, похоже, есть несколько способов добиться этого ... Я просто не уверен, что это лучший подход для меня.Roslyn добавить новый метод к существующему классу
Итак, давайте предположим, что пользователь имеет свое решение открыть в Visual Studio 2015. Они нажимают на мой Расширение и (через форму), они говорят мне, что они хотят, чтобы добавить следующее определение метода к интерфейсу:
GetSomeDataResponse GetSomeData(GetSomeDataRequest request);
Они также говорят мне название интерфейса, это ITheInterface.
интерфейс уже имеет некоторый код в нем:
namespace TheProjectName.Interfaces
{
using System;
public interface ITheInterface
{
/// <summary>
/// A lonely method.
/// </summary>
LonelyMethodResponse LonelyMethod(LonelyMethodRequest request);
}
}
Ладно, так что я могу загрузить документ интерфейса, используя следующие:
Document myInterface = this.Workspace.CurrentSolution?.Projects?
.FirstOrDefault(p
=> p.Name.Equals("TheProjectName"))
?.Documents?
.FirstOrDefault(d
=> d.Name.Equals("ITheInterface.cs"));
Итак, что это лучший способ, чтобы теперь добавить мой новый метод для этого существующего интерфейса, идеально написанный в комментарии XML (комментарий с тройной слэш)? Имейте в виду, что типы запросов и ответов (GetSomeDataRequest и GetSomeDataResponse), возможно, еще не существуют. Я очень новичок в этом, поэтому, если вы можете предоставить примеры кода, это было бы потрясающе.
UPDATE
я решил, что (возможно) лучший подход был бы просто вводить в каком-то тексте, а не пытаться программно создать декларацию методы.
Я попытался следующие, но в конечном итоге с тем исключением, что я не постигнуть:
SourceText sourceText = await myInterface.GetTextAsync();
string text = sourceText.ToString();
var sb = new StringBuilder();
// I want to all the text up to and including the last
// method, but without the closing "}" for the interface and the namespace
sb.Append(text.Substring(0, text.LastIndexOf("}", text.LastIndexOf("}") - 1)));
// Now add my method and close the interface and namespace.
sb.AppendLine("GetSomeDataResponse GetSomeData(GetSomeDataRequest request);");
sb.AppendLine("}");
sb.AppendLine("}");
инспектирующих это, все это хорошо (мой реальный код добавляет форматирование и XML комментарии, но удалены, что для ясности).
Таким образом, зная, что они неизменны, я пытался спасти его следующим образом:
var updatedSourceText = SourceText.From(sb.ToString());
var newInterfaceDocument = myInterface.WithText(updatedSourceText);
var newProject = newInterfaceDocument.Project;
var newSolution = newProject.Solution;
this.Workspace.TryApplyChanges(newSolution);
Но это создавало следующее исключение:
bufferAdapter is not a VsTextDocData
в Microsoft.VisualStudio.Editor. Реализация. VsEditorAdaptersFactoryService.GetAdapter (буферный адаптер IVsTextBuffer) в Microsoft.VisualStudio.Editor.Implementation.VsEditorAdaptersFactoryService.GetDocumentBuffer (IVsTextBuffer bufferAdapter)на Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.InvisibleEditor..ctor (IServiceProvider ServiceProvider, струнного Filepath, Boolean, Boolean needsSave needsUndoDisabled) в Microsoft.VisualStudio.LanguageServices.RoslynVisualStudioWorkspace.OpenInvisibleEditor (IVisualStudioHostDocument hostDocument) в Microsoft.VisualStudio. LanguageServices.Implementation.ProjectSystem.DocumentProvider.StandardTextDocument.UpdateText (SourceText newText) на Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.VisualStudioWorkspaceImpl.ApplyDocumentTextChanged (documentId documentId, SourceText newText) на Microsoft.CodeAnalysis.Workspace.ApplyProjectChanges (ProjectChanges projectChanges) в Microsoft.CodeAnalysis.Workspace.TryApplyChanges (Решение newSolution) в Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.VisualStudioWorkspaceImpl.TryApplyChanges (Решение newSolution)
Возможно, вам необходимо изменить существующий «SourceText» (к которому добавлена дополнительная информация о исходном файле), вызывая 'SourceText.WithChanges (новый TextChange (...))', [см. Этот ответ] (http: //stackoverflow.com/a/37553697/155005). – m0sa