Quiero generar una clase estática que debería tener un método que dependa de otras clases en un ensamblaje de referencia específico.
un ejemplo simplificado:
// 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() } Quiero encontrar las clases de Entity en el proyecto Core y generar una clase en el proyecto de Persistence . El problema es que no se puede acceder a mi proyecto Core y ya está compilado antes que Persistence . ¿Debo usar la reflexión o leer manualmente las Entidades centrales? ¿O hay una mejor manera de acceder a SyntaxTree en el proyecto Core ?
Debido a que el proyecto Core ya está compilado, no podemos acceder a SyntaxTree, pero podemos revisar la compilación para obtener los ensamblajes a los que se hace referencia, luego mirar esos ensamblajes y encontrar los símbolos .
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); }Espero que este ejemplo ayude a otros.