【问题标题】:generate source based on other assembly classes (c# source generator)基于其他程序集类生成源码(c#源码生成器)
【发布时间】:2021-09-04 08:59:39
【问题描述】:

我想生成一个静态类,该类应该有一个方法,具体取决于特定参考程序集中的其他类。

一个简化的例子:

// Generator.csproj
[Generator]
   public class MyGenerator : ISourceGenerator
   {
      public void Initialize(GeneratorInitializationContext context)
      {
          // Register a factory that can create our custom syntax receiver
          context.RegisterForSyntaxNotifications(() => new MySyntaxReceiver());
      }

      public void Execute(GeneratorExecutionContext context)
      {
          // var syntaxReceiver = (MySyntaxReceiver)context.SyntaxReceiver;
      }
   }

    private class MySyntaxReceiver : ISyntaxReceiver
    {
       ....
    }
// Core.csproj
// namespace Core.Entities
class Entity1 : IAccessControl {}
class Entity2  {}
class Entity3 : IAccessControl {}
// Persistence.csproj => has a reference to Core project and the Generator
// this class should be generated ...
static class GeneratedClass
{
   public static void DoSomethingEntity1()
   public static void DoSomethingEntity3()
}

我想在Core项目中找到Entity类,并在Persistence项目中生成一个类, 问题是我的Core 项目无法访问,它已经在Persistence 之前编译。我应该使用反射还是手动读取核心实体?或者有没有更好的方法来访问 Core 项目中的 SyntaxTree?

【问题讨论】:

    标签: c# sourcegenerators csharp-source-generator


    【解决方案1】:

    由于Core 项目已经编译,我们无法访问 SyntaxTree,但我们可以通过编译来获取引用的程序集,然后查看这些程序集并找到 符号。

    public void Execute(GeneratorExecutionContext context)
    {
    // finding Core reference assembly Symbols
     IAssemblySymbol assemblySymbol = 
    context.Compilation.SourceModule.ReferencedAssemblySymbols.First(q => q.Name == "Core");
    
    // use assembly symbol to get namespace and type symbols
    // all members in namespace Core.Entities
    var members = assemblySymbol.GlobalNamespace.
                                 GetNamespaceMembers().First(q => q.Name == "Core")                                       
                                .GetNamespaceMembers().First(q => q.Name == "Entities")
                                .GetTypeMembers().ToList();
    
    var targets = new HashSet<INamedTypeSymbol>();
    
    // find classes that implemented IAccessControl
    foreach (var member in members.Where(m => m.AllInterfaces.Any(i => i.Name == "IAccessControl")))
    {
       targets.Add(member); // Entity1 Entity3
    }
    
    
    // generate source using targets ...
    // context.AddSource("GeneratedClass", source);
    }
    
    

    希望这个例子对其他人有所帮助。

    【讨论】:

      猜你喜欢
      • 2022-01-01
      • 2013-06-24
      • 1970-01-01
      • 2015-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多