简体   繁体   中英

Replace all class usages using roslyn

What I am trying to do: Let's assume we have a class Class1 inside assembly OldAssembly . This assembly is referenced by a number of unknown projects. I am going to move this class into a new assembly NewAssembly , eventually name and namespace would also change. Now all usages must be adjusted. I want to create a tool which will automate these code adjustments.

What I did so far: I have played around with 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);

but it renames also the source class. So I have looked into the Renamer code and tried to adapt it for my use case, but failed due to some internals used in there.

Question: How can I automate code adjustments after moving a class from one assembly into another.

You can achieve what you're looking for by:

  1. Renaming all usages of the class throughout the entire solution
  2. Replacing the renamed class itself with its original 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; } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM