1

我正在尝试做的事情: 假设我们Class1在 assembly中有一个类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代码并尝试对其进行调整以适应我的用例,但由于其中使用了一些内部组件而失败了。

问题: 将一个类从一个程序集移到另一个程序集后,如何自动调整代码。

4

1 回答 1

4

您可以通过以下方式实现您的目标:

  1. 在整个解决方案中重命名类的所有用法
  2. 用原来的自己替换重命名的类本身。

    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;
    }
    
于 2016-04-12T01:44:16.663 回答