简体   繁体   English

使用Roslyn替换方法

[英]Replace a method using Roslyn

I am trying to merge two C# file contents using Roslyn. 我正在尝试使用Roslyn合并两个C#文件内容。 I need to replace certain methods (marked for update) in the older version with newer ones. 我需要用较新的方法替换旧版本中的某些方法(标记为更新)。 I have traversed all the members in both the documents and marked the methods that require changes into a list. 我遍历了两个文档中的所有成员,并将需要更改的方法标记为列表。

class Token
{
    public string Name;  // unique identifier
    public SyntaxNode Node;  // actual node in the document
}

Now I have two Token lists viz, OldTokens and NewTokens. 现在,我有两个令牌列表,即OldTokens和NewTokens。 I need to overwrite the old methods with corresponding new ones. 我需要用相应的新方法覆盖旧方法。

foreach (Token oldt in OldTokens)
{
    Token newt = NewTokens.Find(m => m.Name == oldt.Name);
    if (newt != null)
    {
        DocumentRoot = DocumentRoot.ReplaceNode(oldt.Node, newt.Node);
    }
}

It wasn't working. 没用 I thought it could be because the DocumentRoot doesn't hold the old node in it immediate member list, as it would appear deep inside the hierarchy of namespace->class->member. 我认为可能是因为DocumentRoot没有将旧节点保留在其直接成员列表中,因为它会深入显示在namespace-> class-> member的层次结构内。 So I tried something like: 所以我尝试了类似的东西:

var nd = existing.Node.Parent.ReplaceNode(existing.Node, miss.Node);
var d2 = existing.Node.Parent.Parent.ReplaceNode(existing.Node.Parent, nd);
DocumentRoot = existing.Node.Parent.Parent.Parent.ReplaceNode(existing.Node.Parent.Parent, d2) as CompilationUnitSyntax;

Which is working but too difficult to handle. 这是可行的,但很难处理。 It would become a mess when there exists nested classes. 当存在嵌套类时,它将变得一团糟。 Is there a better way? 有没有更好的办法?

Secondly, in the result, I am missing the code comments. 其次,结果是我缺少代码注释。 I tried with the overload for ReplaceNode method, which is quite confusing as it won't take the new method node. 我尝试了ReplaceNode方法的重载,这很令人困惑,因为它不会采用新的方法节点。

Thanks 谢谢

Due to the fact that Roslyn SyntaxNode objects are immutable, every time you call "ReplaceNode", you get a whole new tree back. 由于Roslyn SyntaxNode对象是不可变的,因此,每次调用“ ReplaceNode”时,都会得到一棵全新的树。 The normal way to solve this problem is to add a SyntaxAnnotation to each node you want to replace. 解决此问题的通常方法是向要替换的每个节点添加SyntaxAnnotation This is a stable marker that will be preserved through tree transformations as long as the node itself isn't replaced. 这是一个稳定的标记,只要不替换节点本身,就可以通过树转换来保留它。

Alternatively, when making many changes to a file like this, you could look at implementing a SyntaxRewriter , instead of just calling ReplaceNode a bunch of times. 另外,当像这样对文件进行许多更改时,您可以考虑实现SyntaxRewriter ,而不仅仅是多次调用ReplaceNode SyntaxRewriter will visit the tree bottom-up, so the node passed to the method will always be from the original SyntaxTree . SyntaxRewriter将自下而上访问树,因此传递给该方法的节点将始终来自原始SyntaxTree However, make sure you first call base.Visit() in any method you override and use the result so that you have the updated version of any nodes that are descendants of the current node. 但是,请确保首先使用任何覆盖和使用结果的方法来调用base.Visit() ,以使您拥有属于当前节点后代的所有节点的更新版本。

Finally, regarding comments, you'll need to copy the trivia ( GetLeadingTrivia() / GetTrailingTrivia() ) from the nodes you are replacing in order to retain it. 最后,关于注释,您需要从要替换的节点复制琐事( GetLeadingTrivia() / GetTrailingTrivia() )以保留它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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