C# 每个类获得一个Roslyn语法接收器

C# 每个类获得一个Roslyn语法接收器,c#,roslyn,sourcegenerators,C#,Roslyn,Sourcegenerators,我有一个简单的源代码生成器,定义为 [Generator] public class NestedObjectGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { context.RegisterForSyntaxNotifications(() => new MySyntaxReceiver()); } public void

我有一个简单的源代码生成器,定义为

[Generator]
public class NestedObjectGenerator : ISourceGenerator
{
  public void Initialize(GeneratorInitializationContext context)
  {
    context.RegisterForSyntaxNotifications(() => new MySyntaxReceiver());
  }
  public void Execute(GeneratorExecutionContext context)
  {
    var recv = (MySyntaxReceiver)context.SyntaxReceiver;
    ClassDeclarationSyntax cds = recv?.Class;
    if (cds is null) return;

    // use cds here
  }

  private class MySyntaxReceiver : ISyntaxReceiver
  {
    public ClassDeclarationSyntax Class { get; private set; }

    public void OnVisitSyntaxNode(SyntaxNode node)
    {
      if (node is ClassDeclarationSyntax cds &&
        cds.Modifiers.Any(SyntaxKind.PartialKeyword))
      Class = cds;
    }
  }
}
我在一个文件上运行这个生成器,该文件中有几个分部类。但是,似乎只调用了一次
Execute()
,并且包含的
Class
是具有
Main()
方法的类,即使文件中还有其他类


因此,我的问题是:如何让
Execute()
在每个受影响的语法节点上运行一次,即在每个部分类上运行一次?

您可以这样更改接收器:

private class MySyntaxReceiver : ISyntaxReceiver
{
  public List<ClassDeclarationSyntax> ClassCandidates { get; } = new();

  public void OnVisitSyntaxNode(SyntaxNode node)
  {
    if (node is ClassDeclarationSyntax cds && cds.Modifiers.Any(SyntaxKind.PartialKeyword))
      ClassCandidates.Add(cds);
  }
}
私有类MySyntaxReceiver:ISyntaxReceiver
{
公共列表类候选对象{get;}=new();
在VisitSyntaxNode(SyntaxNode节点)上的公共无效
{
if(节点为ClassDeclarationSyntax cds&&cds.Modifiers.Any(SyntaxKind.PartialKeyword))
添加(CD);
}
}
然后在源生成器的Execute方法中,您可以在收集的所有节点上循环。 我是从一个信息丰富的视频中得到这个方法的

下面是演示中的github和演示,我从以下示例中学到了这一点:


您可以这样更改接收器:

private class MySyntaxReceiver : ISyntaxReceiver
{
  public List<ClassDeclarationSyntax> ClassCandidates { get; } = new();

  public void OnVisitSyntaxNode(SyntaxNode node)
  {
    if (node is ClassDeclarationSyntax cds && cds.Modifiers.Any(SyntaxKind.PartialKeyword))
      ClassCandidates.Add(cds);
  }
}
私有类MySyntaxReceiver:ISyntaxReceiver
{
公共列表类候选对象{get;}=new();
在VisitSyntaxNode(SyntaxNode节点)上的公共无效
{
if(节点为ClassDeclarationSyntax cds&&cds.Modifiers.Any(SyntaxKind.PartialKeyword))
添加(CD);
}
}
然后在源生成器的Execute方法中,您可以在收集的所有节点上循环。 我是从一个信息丰富的视频中得到这个方法的

下面是演示中的github和演示,我从以下示例中学到了这一点: