我想做什么:
假设我们在程序集Class1
中有一个类OldAssembly
。
该程序集由许多未知项目引用。
我将把这个类移动到一个新的程序集NewAssembly
,最终名称和命名空间也会改变。现在必须调整所有用法。
我想创建一个自动执行这些代码调整的工具。
到目前为止我做了什么:
我玩过roslyn Renamer
:
var workspace = MSBuildWorkspace.Create();
var originalSln = workspace.OpenSolutionAsync(@"D:\spikes\ToBeFixed\ToBeFixed.sln").Result;
var project = originalSln.Projects.Single();
var compilation = project.GetCompilationAsync().Result;
var renameFrom = compilation.GetSymbolsWithName(s => s.Contains("Class1")).Single();
const string renameTo = "Class2";
var optionSet = originalSln.Workspace.Options;
var modifiedSln = Renamer.RenameSymbolAsync(originalSln, renameFrom, renameTo, optionSet).Result;
workspace.TryApplyChanges(modifiedSln);
但它也重命名了源类。所以我查看了Renamer
代码并尝试根据我的用例进行调整,但由于在那里使用了一些内部结构而失败了。
问题: 在将类从一个程序集移动到另一个程序集后,如何自动执行代码调整。
答案 0 :(得分:3)
您可以通过以下方式实现您所寻找的目标:
用其原始self替换重命名的类本身。
public async static Task TestingRenamer()
{
var code = @"
using System;
//We do not want to rename MyClass (we want to keep it the same)
public class MyClass
{
public MyClass()
{
}
}
public class Program
{
public static void Main()
{
//We want to rename this usage
var x = new MyClass();
}
}";
var newClassName = "MY_NEW_CLASS_NAME";
var document = getDocumentForCode(code);
var compilation = await document.Project.GetCompilationAsync();
var root = await document.GetSyntaxRootAsync();
var originalClass = root.DescendantNodesAndSelf().OfType<ClassDeclarationSyntax>().First();
var model = compilation.GetSemanticModel(root.SyntaxTree);
var originalSymbol = model.GetDeclaredSymbol(originalClass);
//Rename all
var newSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, originalSymbol, newClassName, document.Project.Solution.Workspace.Options);
//Revert the original class
var newDocument = newSolution.GetDocument(document.Id);
var newSyntaxRoot = await newDocument.GetSyntaxRootAsync();
var newClass = newSyntaxRoot.DescendantNodes().OfType<ClassDeclarationSyntax>().Where(n => n.Identifier.ToString() == newClassName).Single();
newSyntaxRoot = newSyntaxRoot.ReplaceNode(newClass, originalClass);
newDocument = newDocument.WithSyntaxRoot(newSyntaxRoot);
//We've now renamed all usages and reverted the class back to its original self.
var finalSolution = newDocument.Project.Solution;
}
//Helper method to build Document
private static Document getDocumentForCode(string code)
{
var ws = new AdhocWorkspace();
var Mscorlib = MetadataReference.CreateFromAssembly(typeof(object).Assembly);
var references = new List<MetadataReference>() { Mscorlib };
var projInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Default, "MyProject", "MyAssembly", "C#", metadataReferences: references);
var project = ws.AddProject(projInfo);
var text = SourceText.From(code);
var myDocument = ws.AddDocument(project.Id, "MyDocument.cs", text);
return myDocument;
}