我正在研究在使用VisualStudioWorkspace更新现有代码的Visual Studio扩展(VSIX)中使用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)可能尚不存在。我很新手,如果您可以提供代码示例,那就太棒了。
更新
我决定(可能)最好的方法是简单地注入一些文本,而不是尝试以编程方式构建方法声明。
我尝试了以下内容,但最终遇到了一个我不理解的异常:
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.Implementation.VsEditorAdaptersFactoryService 中,通过传入的 IVsTextBuffer 缓冲适配器获取适配器。然后通过缓冲适配器获取文档缓冲区,并在 Microsoft.VisualStudio.LanguageServices.RoslynVisualStudioWorkspace 类中打开一个不可见的编辑器 IVisualStudioHostDocument。接下来,在 Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.DocumentProvider.StandardTextDocument 类中更新文本内容,以及在 Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.VisualStudioWorkspaceImpl 类中应用文档更改。最后,将这些更改应用到项目系统和解决方案中,以确保修改生效。
SourceText.WithChanges(new TextChange(...))
来更改现有的SourceText
(它附带了其他源文件信息),参见此答案 中的示例。 - m0sa