基于其他程序集 类 生成源代码(c# 源代码生成器)
generate source based on other assembly classes (c# source generator)
我想生成一个静态 class 应该有一个方法依赖于特定 参考程序集 .
中的其他 classes
一个简化的例子:
// 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
classes,在Persistence
项目中生成一个class,
问题是我的 Core
项目不可访问,它已经在 Persistence
之前编译。我应该使用反射还是手动读取核心实体?还是有更好的方法来访问 Core
项目中的 SyntaxTree?
因为 Core
项目已经编译,我们无法访问 SyntaxTree,但我们可以通过编译获取引用的程序集,然后查看这些程序集并找到 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);
}
希望这个例子对其他人有帮助。
我想生成一个静态 class 应该有一个方法依赖于特定 参考程序集 .
中的其他 classes一个简化的例子:
// 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
classes,在Persistence
项目中生成一个class,
问题是我的 Core
项目不可访问,它已经在 Persistence
之前编译。我应该使用反射还是手动读取核心实体?还是有更好的方法来访问 Core
项目中的 SyntaxTree?
因为 Core
项目已经编译,我们无法访问 SyntaxTree,但我们可以通过编译获取引用的程序集,然后查看这些程序集并找到 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);
}
希望这个例子对其他人有帮助。