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
相关产品推荐
相关产品推荐

