You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C# IIncrementalGenerator源码生成中获取Attribute属性值

解决源代码生成器中获取自定义Attribute属性值的问题

核心思路

你当前的代码仅传递了类的语法节点到Execute方法,未携带Attribute的参数值。需要在语法解析阶段就提取出Attribute构造函数的参数(即Aggregate的值),并和类节点一起传递到后续生成逻辑中。

具体实现步骤

1. 定义数据承载类

创建一个记录类,统一保存需要的类节点和属性值信息:

public record EventApplyInfo(ClassDeclarationSyntax ClassDeclaration, string AggregateName);

2. 修改属性解析逻辑

调整GetSemanticTargetForGeneration方法,不再返回ClassDeclarationSyntax,而是解析Attribute的构造函数参数,返回封装好的EventApplyInfo:

private static EventApplyInfo? GetSemanticTargetForGeneration(GeneratorAttributeSyntaxContext context, CancellationToken ct)
{
    var attributeData = context.Attributes.First();
    string fullName = attributeData.AttributeClass.ToDisplayString();

    if (fullName == EventApplyAttribute)
    {
        if (context.TargetNode is not ClassDeclarationSyntax classDeclaration)
            return null;

        // 解析构造函数第一个参数(对应Aggregate属性)
        if (attributeData.ConstructorArguments.FirstOrDefault().Value is string aggregateName)
        {
            return new EventApplyInfo(classDeclaration, aggregateName);
        }
    }

    return null;
}

3. 调整增量生成器的类型映射

修改Initialize方法中的增量提供者类型,从ClassDeclarationSyntax改为EventApplyInfo:

public void Initialize(IncrementalGeneratorInitializationContext context)
{
    IncrementalValuesProvider<EventApplyInfo?> eventApplyInfos = context.SyntaxProvider
        .ForAttributeWithMetadataName(
            EventApplyAttribute,
            predicate: (node, _) => node is ClassDeclarationSyntax,
            transform: (ctx, ct) => GetSemanticTargetForGeneration(ctx, ct))
        .Where(static m => m is not null);

    IncrementalValueProvider<(Compilation, ImmutableArray<EventApplyInfo>)> compilationAndInfos
    = context.CompilationProvider.Combine(eventApplyInfos.Collect()
        .Select(static infos => infos.Where(info => info != null).ToImmutableArray()!));

    context.RegisterSourceOutput(compilationAndInfos,
        static (spc, source) => Execute(source.Item1, source.Item2, spc));
}

4. 在Execute中使用属性值

修改Execute方法参数,直接获取每个类对应的AggregateName:

private static void Execute(Compilation compilation, ImmutableArray<EventApplyInfo> eventApplyInfos, SourceProductionContext context)
{
    foreach (var info in eventApplyInfos)
    {
        // 拿到示例中的"BaseClass"值和对应的类节点
        string aggregateName = info.AggregateName;
        ClassDeclarationSyntax classDecl = info.ClassDeclaration;
        
        // 后续生成代码逻辑示例:输出调试信息
        context.ReportDiagnostic(Diagnostic.Create(
            new DiagnosticDescriptor("TEST001", "Aggregate Info", "Class {0} applies to aggregate {1}", "SourceGen", DiagnosticSeverity.Info, true),
            classDecl.GetLocation(),
            classDecl.Identifier.Text,
            aggregateName));
    }
}

补充说明

如果你的Attribute是通过命名参数设置属性(比如[EventApply(Aggregate = "BaseClass")]),则需要通过AttributeData.NamedArguments解析,对应代码:

var aggregateArg = attributeData.NamedArguments.FirstOrDefault(arg => arg.Key == nameof(EventApplyAttribute.Aggregate));
if (aggregateArg.Value.Value is string aggregateName)
{
    // 使用解析得到的aggregateName
}

内容的提问来源于stack exchange,提问作者Dani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:40:56