【问题标题】:Rename interface using Roslyn not working使用 Roslyn 重命名界面不起作用
【发布时间】:2023-01-18 04:42:03
【问题描述】:

我想重命名一个类、它的基类和它支持的接口。例如我想重写这个:-

public class CustomerDAL : DALBase, ICustomerDAL

对此:-

public class CustomerRepository : RepositoryBase, ICustomerRepository

所以我写了这个 CSharpSyntaxRewriter:-

public class RenameBaseClassAndInterface : CSharpSyntaxRewriter
{
    public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
    {
        if (node.Identifier.Text.Contains("DAL"))
        {
            string className = node.Identifier.Text.Replace("DAL", "Repository");

            node = node.ReplaceToken(node.Identifier, SyntaxFactory.Identifier(className));

            if (node.BaseList != null && node.BaseList.Types != null)
            {
                foreach (BaseTypeSyntax baseTypeSyntax in node.BaseList.Types)
                {
                    TypeSyntax typeSyntax = baseTypeSyntax.Type;
                    IdentifierNameSyntax identifierNameSyntax = (IdentifierNameSyntax)typeSyntax;
                    if (identifierNameSyntax.Identifier.ToString() == "DALBase")
                    {
                        node = node.ReplaceToken(identifierNameSyntax.Identifier, SyntaxFactory.Identifier("RepositoryBase"));
                    }
                    else if (identifierNameSyntax.Identifier.ToString().Contains("DAL"))
                    {
                        string repositoryInterfaceName = identifierNameSyntax.Identifier.ToString().Replace("DAL", "Repository");
                        node = node.ReplaceToken(identifierNameSyntax.Identifier, SyntaxFactory.Identifier(repositoryInterfaceName));
                    }
                }
            }
        }

        return base.VisitClassDeclaration(node);
    }
}

我实际得到的是:-

public class CustomerRepository : RepositoryBase, ICustomerDAL

(即 ICustomerDAL 不会重命名为 ICustomerRepository)。

我可以单步执行我的代码,我看到它到达并执行了重命名接口的代码并且没有发生错误,它只是不起作用。我怀疑这是因为它在旧节点而不是新节点上进行重命名,但我看不出我做错了什么。

有任何想法吗?

【问题讨论】:

    标签: c# roslyn


    【解决方案1】:

    您的 foreach 循环试图更新基本列表中的所有标记。第一次调用 ReplaceToken 后,您已经创建了一个具有新令牌标识的新节点,因此第二次调用 ReplaceToken 时,您将令牌从原始节点传递到正在发生的调用在新节点上。所以第二次调用可能是返回现有节点而不是进行替换。 (不幸的是,如果 ReplaceToken 找不到令牌,它就是空操作,这通常会造成混淆。)

    代替编写的 foreach 循环,将需要替换(或至少分析)的标记添加到列表中,然后调用 ReplaceTokens。这需要一个要(可能)替换的标记列表,以及一个我们将为每个标记调用的 lambda 来重写它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      • 2017-01-27
      • 2018-06-19
      • 2018-02-06
      • 1970-01-01
      • 1970-01-01
      • 2014-05-12
      相关资源
      最近更新 更多