gpt4 book ai didi

c# - 源生成器 : Attribute ConstructorArguments is empty

转载 作者:行者123 更新时间:2023-12-04 16:35:58 25 4
gpt4 key购买 nike

我正在编写一个源代码生成器,但正在努力获取传递给我的属性的构造函数的参数的值。
我将以下内容注入(inject)到编译中:

namespace Richiban.Cmdr
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class CmdrMethod : System.Attribute
{
private readonly string _alias;

public CmdrMethod(string alias)
{
_alias = alias;
}
}
}
然后在我的示例应用程序中,我有以下内容:
public static class InnerContainerClass
{
[CmdrMethod("test")]
public static void AnotherMethod(Data data)
{
Console.WriteLine($"In {nameof(AnotherMethod)}, {new { data }}");
}
}

编译时没有错误或警告,我成功地找到了所有用我的 CmdrMethod 修饰的方法。属性,但我无法获取传递给属性的值,因为出于某种原因, ConstructorArguments该属性的属性为空:
private static ImmutableArray<string> GetAttributeArguments(
IMethodSymbol methodSymbol,
string attributeName)
{
var attr = methodSymbol
.GetAttributes()
.Single(a => a.AttributeClass?.Name == attributeName);

var arguments = attr.ConstructorArguments;

if (methodSymbol.Name == "AnotherMethod")
Debugger.Launch();

return arguments.Select(a => a.ToString()).ToImmutableArray();
}
See how the ConstructorArguments property is empty
我误解了这个 API 吗?我究竟做错了什么?

最佳答案

Compilation是不可变的。当你为你的属性添加源代码时,你仍然有一个 Compilation对属性一无所知的对象。这会导致 AttributeClass成为 ErrorType正如@jason-malinowski 提到的那样。这以这种源生成器而闻名,解决方案很简单。新建Compilation用你注入(inject)的符号,然后得到一个 SemanticModel来自新Compilation :

            // You should already have something similar to the following two lines.
SourceText attributeSourceText = SourceText.From("CmdrMethod source code here", Encoding.UTF8);

context.AddSource("CmdrMethod.g.cs" /* or whatever name you chose*/, attributeSourceText);

// This is the fix.
ParseOptions options = ((CSharpCompilation)context.Compilation).SyntaxTrees[0].Options;
SyntaxTree attributeTree = CSharpSyntaxTree.ParseText(atttributeSourceText, (CSharpParseOptions)options);
Compilation newCompilation = context.Compilation.AddSyntaxTrees(attributeTree);
// Get the semantic model from 'newCompilation'. It should have the information you need.


更新:从 Microsoft.CodeAnalysis 开始,体验变得更好3.9 软件包,您现在可以在 Initialize 中添加属性而不是 Execute :
        public void Initialize(GeneratorInitializationContext context)
{
// Register the attribute source
context.RegisterForPostInitialization((i) => i.AddSource("CmdrMethod.g.cs", attributeText));
// .....
}
然后,您可以直接使用您在 Execute 中获得的编译。 .
AutoNotify sample .

关于c# - 源生成器 : Attribute ConstructorArguments is empty,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69853257/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com