使用Roslyn更改文件

我正在尝试编写一个命令行工具,使用Roslyn修改一些代码。 一切似乎都顺利:打开解决方案,更改解决方案,Workspace.TryApplyChanges方法返回true。 但是,磁盘上没有更改实际文件。 这是怎么回事? 下面是我正在使用的顶级代码。

static void Main(string[] args) { var solutionPath = args[0]; UpdateAnnotations(solutionPath).Wait(); } static async Task UpdateAnnotations(string solutionPath) { using (var workspace = MSBuildWorkspace.Create()) { var solution = await workspace.OpenSolutionAsync(solutionPath); var newSolution = await SolutionAttributeUpdater.UpdateAttributes(solution); var result = workspace.TryApplyChanges(newSolution); Console.WriteLine(result); return result; } } 

我使用您的代码构建了一个简短的程序,并收到了我期望的结果 – 问题似乎存在于SolutionAttributeUpdater.UpdateAttributes方法中。 我使用您的base main和UpdateAnnotations方法使用以下实现收到了这些结果:

 public class SolutionAttributeUpdater { public static async Task UpdateAttributes(Solution solution) { foreach (var project in solution.Projects) { foreach (var document in project.Documents) { var syntaxTree = await document.GetSyntaxTreeAsync(); var root = syntaxTree.GetRoot(); var descentants = root.DescendantNodes().Where(curr => curr is AttributeListSyntax).ToList(); if (descentants.Any()) { var attributeList = SyntaxFactory.AttributeList( SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("Cookies"), SyntaxFactory.AttributeArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.AttributeArgument( SyntaxFactory.LiteralExpression( SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(@"Sample")) )}))))); root = root.ReplaceNodes(descentants, (node, n2) => attributeList); solution = solution.WithDocumentSyntaxRoot(document.Id, root); } } } return solution; } } 

它在样本解决方案中使用以下类进行了测试:

 public class SampleClass { [DataMember("Id")] public int Property { get; set; } [DataMember("Id")] public void DoStuff() { DoStuff(); } } 

它产生了以下输出:

 public class SampleClass { [Cookies("Sample")] public int Property { get; set; } [Cookies("Sample")] public void DoStuff() { DoStuff(); } } 

如果你看一下UpdateAttributes方法,我必须用ReplaceNodes替换节点,并通过调用WithDocumentSyntaxRoot更新解决方案。

我会假设这两个调用中的任何一个缺失或者根本没有任何改变 – 如果你调用workspace.TryApplyChanges(解决方案),你仍然会收到true作为输出。

请注意,使用root.ReplaceNode()而不是root.ReplaceNodes()的多次调用也可能导致错误,因为只有第一次更新实际用于修改后的文档 – 这可能会让您相信根本没有任何更改,取决于实施。