Roslyn 的 SyntaxReceiver - 获取类实现接口

Posted

技术标签:

【中文标题】Roslyn 的 SyntaxReceiver - 获取类实现接口【英文标题】:Roslyn's SyntaxReceiver - Get Classes Implementing Interface 【发布时间】:2021-09-02 07:07:08 【问题描述】:

我正在尝试开发一个源代码生成器,以使用该接口在部分类上自动实现一个接口。

我相信这一定是Microsoft's new Source Generators 的常见用例,甚至在Roslyn Source Generator Cookbook 中被列为用例,但没有示例实现。

我在 Roslyn Analyzers 中搜索过,但很难找到针对此场景的问题。

在说明书中,他们使用一个 SyntaxReceiver 类来过滤哪些语法节点应该由 Execute 调用处理:

        class SluggableSyntaxReceiver : ISyntaxReceiver
        
            public List<ClassDeclarationSyntax> ClassesToAugment  get;  = new List<ClassDeclarationSyntax>();

            public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
            
                // Business logic to decide what we're interested in goes here
                if(syntaxNode is ClassDeclarationSyntax cds && cds.HasInterface("IChangeTracked"))
                    ClassesToAugment.Add(cds)
            

        

查看说明书了解生成器的实现细节。

我要确定的是如何在 ClassDeclarationSyntax 节点上实现我的 HasInterface 扩展。

        public static bool HasInterface(this ClassDeclarationSyntax source, string interfaceName)
        
            IEnumerable<TypeSyntax> baseTypes = source.BaseList.Types.Select(baseType=>baseType.Type);
            // Ideally some call to do something like...
            return baseTypes.Any(baseType=>baseType.Name==interfaceName);
        

我该怎么做:

    从 ClassDeclarationSyntax 中获取 BaseList 属性, 确定类是否为部分类 访问接口 确定是否有任何接口属于特定类型。

【问题讨论】:

【参考方案1】:

我必须相信有比我所做的更好的方法来做到这一点,但就其价值而言,这里有一个有效的实现,它可以确定特定的 ClassDeclarationSyntax 是否显式地实现了一个接口:

        /// <summary>Indicates whether or not the class has a specific interface.</summary>
        /// <returns>Whether or not the SyntaxList contains the attribute.</returns>
        public static bool HasInterface(this ClassDeclarationSyntax source, string interfaceName)
        
            IEnumerable<BaseTypeSyntax> baseTypes = source.BaseList.Types.Select(baseType => baseType);

            // To Do - cleaner interface finding.
            return baseTypes.Any(baseType => baseType.ToString() ==interfaceName);
        

【讨论】:

以上是关于Roslyn 的 SyntaxReceiver - 获取类实现接口的主要内容,如果未能解决你的问题,请参考以下文章

Roslyn:如何修复 RS2008 警告?

Roslyn

RyuJIT 和 Roslyn 有啥区别?

使用 Roslyn 生成格式良好的语法

Roslyn

Roslyn - 如何用多个节点替换多个节点?