【问题标题】:Move to Resource refactoring转向资源重构
【发布时间】:2017-01-16 18:15:48
【问题描述】:

我正在尝试进行自己的 Move to Resource 重构(就像在 ReSharper 中找到的那样)。在我的 CodeAction.GetChangedDocumentAsync 方法中,我正在执行以下 3 个步骤:

  1. 使用 XmlDocument 将我的资源添加到 Resources.resx 文件
  2. 使用 DTE 运行自定义工具来更新 Resources.Designer.cs 文件
  3. SyntaxNode.ReplaceNode 新资源的限定标识符替换文字字符串

第 1 步和第 2 步都可以,但第 3 步不起作用。如果我删除第 2 步,第 3 步就可以了。

我不知道是因为我正在混合 Roslyn 和 DTE,还是因为第 2 步在解决方案中生成了新代码,而我的缓存上下文变得无效。

// Add the resource to the Resources.resx file
var xmlDoc = new XmlDocument();
xmlDoc.Load(resxPath);
XmlNode node = xmlDoc.SelectSingleNode($"//data[@name='{resourceIndentifierName}']");
if (node != null) return;
XmlElement dataElement = xmlDoc.CreateElement("data");

XmlAttribute nameAtt = xmlDoc.CreateAttribute("name");
nameAtt.Value = resourceIndentifierName;
dataElement.Attributes.Append(nameAtt);

XmlAttribute spaceAtt = xmlDoc.CreateAttribute("space", "xml");
spaceAtt.Value = "preserve";
dataElement.Attributes.Append(spaceAtt);

XmlElement valueElement = xmlDoc.CreateElement("value");
valueElement.InnerText = value;
dataElement.AppendChild(valueElement);

XmlNode rootNode = xmlDoc.SelectSingleNode("//root");
Debug.Assert(rootNode != null, "rootNode != null");
rootNode.AppendChild(dataElement);
xmlDoc.Save(resxPath);

// Update the Resources.Designer.cs file
var dte = (DTE2)Package.GetGlobalService(typeof(SDTE));
ProjectItem item = dte.Solution.FindProjectItem(resxPath);
((VSProjectItem) item.Object)?.RunCustomTool();

// Replace the node
SyntaxNode oldRoot = await context.Document.GetSyntaxRootAsync(cancellationToken)
  .ConfigureAwait(false);
SyntaxNode newRoot = oldRoot.ReplaceNode(oldNode, newNode);
return context.Document.WithSyntaxRoot(newRoot);

【问题讨论】:

  • newNode 是什么?
  • newNodeQualifiedName:Properties.Resources.MyResource
  • 到底发生了什么?但你不能这样做;代码动作必须是纯函数。例如,悬停预览呢?
  • 我暂时禁用了预览 (stackoverflow.com/q/37435740/200443)
  • 第一次运行时,资源被添加到 .resx 文件中,但代码没有任何变化。在第二次运行时,资源存在,因此 .resx 保持不变,代码已更改。

标签: c# visual-studio roslyn resx vsix


【解决方案1】:

这是因为第 2 步在解决方案中生成了新代码,而我的缓存上下文变得无效

这就是正在发生的事情。当您调用RunCustomTool 时,Visual Studio 文件观察器 api 会告诉 roslyn 文件已更新,并且 roslyn 会生成一组新的解决方案快照。当您尝试应用您的 codefix 时,roslyn 会查看您的 codefix 来自的解决方案快照,发现它与当前快照不匹配,并且无法应用它。

【讨论】:

  • 我已经实现了GetChangedSolutionAsync 而不是GetChangedDocumentAsync,我现在正在使用Roslyn 更新.Designer.cs,而不是使用RunCustomTool。而且效果很好。非常感谢。
  • 最后还是不行,因为我的重构和ResXFileCodeGenerator有冲突。每次我修改 .resx 时,.Designer.cs 都会由 ResXFileCodeGenerator 更新,并且我的快照变得无效。如果我禁用 ResXFileCodeGenerator,.Designer.cs 将从解决方案中消失。我要把它变成一个标准的 VS 命令。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多