使用Roslyn访问和修改解决方案中的所有文档

本文关键字:文档 解决方案 Roslyn 访问 修改 使用 | 更新日期: 2023-09-27 18:09:41

我想使用Roslyn在给定的解决方案中遍历每个项目中的所有文档。

这是我现在的代码:

var msWorkspace = MSBuildWorkspace.Create();
var solution = await msWorkspace.OpenSolutionAsync(solutionPath);
foreach (var project in solution.Projects)
{
    foreach (var document in project.Documents)
    {
        if (document.SourceCodeKind != SourceCodeKind.Regular)
            continue;
        var doc = document;
        foreach (var rewriter in rewriters)
        {
            doc = await rewriter.Rewrite(doc);
        }
        if (doc != document)
        {
            Console.WriteLine("changed {0}",doc.Name);
            //save result
            //the solution is now changed and the next document to be processed will belong to the old solution
            msWorkspace.TryApplyChanges(doc.Project.Solution);
        }                    
    }
}

这里的问题是as Roslyn在很大程度上是不可变的。在第一个"msWorkspace"之后。TryApplyChanges",解决方案和文档现在被新版本替换。

所以下一次迭代仍然会遍历旧版本。有什么方法可以用罗斯林的习惯方式来做吗?还是我得用一些for(int projectIndex = 0;projectIndex < solution.Projects.count) {式的手法?

使用Roslyn访问和修改解决方案中的所有文档

这个张贴在Roslyn gitter聊天中的解决方案做到了这一点并解决了问题。

var solution = await msWorkspace.OpenSolutionAsync(solutionPath);
foreach (var projectId in solution.ProjectIds)
{
    var project = solution.GetProject(projectId);
    foreach (var documentId in project.DocumentIds)
    {
        Document document = project.GetDocument(documentId);
        if (document.SourceCodeKind != SourceCodeKind.Regular)
            continue;
        var doc = document;
        foreach (var rewriter in rewriters)
        {
            doc = await rewriter.Rewrite(doc);
        }
        project = doc.Project;
    }
    solution = project.Solution;
}
msWorkspace.TryApplyChanges(solution);

在这种情况下,更改不再在迭代之间被丢弃,因为所有内容都建立在上一次迭代的结果之上。(也就是说,文档和项目是通过ID获取的,而不是通过遍历原始结构的枚举器获取的)