I want to generate a static class that should have a method depending on other classes in specific reference assembly.
a simplified example:
// 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()
}
I want to find the Entity
classes in the Core
project and generate a class in the Persistence
project,
The problem is my Core
project is not accessible and it is already compiled before Persistence
. should I use reflection or manually read the Core Entities ? or is there a better way to access SyntaxTree in the Core
project?
Because the Core
project is already compiled we can not access SyntaxTree but we can go through the compilation to get the referenced assemblies, then look through those assemblies and find the symbols.
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);
}
hope this example help others.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With