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

SourceGenerator开发中Attribute的ConstructorArguments为空问题求助

问题原因与解决方案

核心错误原因

  • Attribute匹配逻辑不严谨:你当前只匹配了Attribute的类名,没有匹配命名空间,大概率获取到的AttributeData实例并非你注入的Richiban.Cmdr.CmdrMethod,而是编译上下文中其他同名的Attribute类,该类没有对应的string参数构造函数,因此ConstructorArguments为空。
  • Attribute注入时机错误:如果你没有在编译的预初始化阶段注入Attribute源码,用户代码中的[CmdrMethod("test")]会被编译器判定为未找到类型,降级为没有构造参数的未知Attribute,自然无法读取构造参数。

修复方案

1. 修正Attribute匹配逻辑

修改匹配规则,同时校验类名和命名空间,确保拿到正确的Attribute实例:

private static ImmutableArray<string> GetAttributeArguments(
            IMethodSymbol methodSymbol,
            string attributeName)
{
    var attr = methodSymbol
        .GetAttributes()
        .Single(a => 
            a.AttributeClass?.Name == attributeName
            && a.AttributeClass.ContainingNamespace.ToDisplayString() == "Richiban.Cmdr");

    // 可选校验:确认构造函数符合预期
    Debug.Assert(attr.AttributeConstructor?.Parameters.Length == 1 
        && attr.AttributeConstructor.Parameters[0].Type.SpecialType == SpecialType.System_String);

    var arguments = attr.ConstructorArguments;
    
    if (methodSymbol.Name == "AnotherMethod")
        Debugger.Launch();

    return arguments.Select(a => a.Value?.ToString() ?? string.Empty).ToImmutableArray();
}

注意:读取参数值要取Value属性而非直接调用ToString,避免出现不符合预期的格式化结果

2. 修正Attribute注入逻辑

无论你用的是ISourceGenerator还是IIncrementalGenerator,都必须在预初始化阶段注入Attribute源码,确保用户代码编译时能正确绑定到你定义的Attribute:

ISourceGenerator注入示例

public void Initialize(GeneratorInitializationContext context)
{
    context.RegisterForPostInitialization(ctx =>
    {
        ctx.AddSource("CmdrMethodAttribute.g.cs", @"
namespace Richiban.Cmdr
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class CmdrMethod : System.Attribute
    {
        private readonly string _alias;

        public CmdrMethod(string alias)
        {
            _alias = alias;
        } 
    }
}");
    });
    // 其他初始化逻辑
}

IIncrementalGenerator注入示例

public void Initialize(IncrementalGeneratorInitializationContext context)
{
    context.RegisterPostInitializationOutput(ctx =>
    {
        ctx.AddSource("CmdrMethodAttribute.g.cs", @"
namespace Richiban.Cmdr
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class CmdrMethod : System.Attribute
    {
        private readonly string _alias;

        public CmdrMethod(string alias)
        {
            _alias = alias;
        } 
    }
}");
    });
    // 其他增量生成逻辑
}

3. 额外排查点

  • 检查用户项目中是否存在自定义的同名CmdrMethodAttribute,如果有会优先绑定到用户定义的类型,和你注入的类型冲突
  • 确认编译过程中没有出现未知Attribute类型的隐式警告,该警告会导致Attribute绑定失败,参数丢失

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 02:24:07