英文:
Read parameters of attribute created by source generator
问题
我有以下的源代码生成器
[Generator]
public class Generator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var output = @"using System;
namespace SourceGeneratorAttributes;
[AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
class GlobalAttribute : Attribute
{
public int OptionalNumber { get; set; } = 10;
public string OptionalString { get; set; } = ""test"";
public GlobalAttribute(string requiredString, int requiredNumber) {}
}
";
context.AddSource("GlobalAttribute.cs", SourceText.From(output, Encoding.UTF8));
var attributes = context.Compilation.Assembly.GetAttributes();
foreach (var attribute in attributes)
{
Console.WriteLine(attribute);
}
}
public void Initialize(GeneratorInitializationContext context)
{
}
}
然后在我使用源代码生成器的项目中,我有以下内容
[assembly:Global("text", 20, OptionalNumber = 33, OptionalString = "random")]
但是如果我在Console.WriteLine(attribute);
上打断点并检查attribute
,我会得到以下结果:
我如何找到错误是什么?为什么所有参数都消失了?
如果我使用不同的属性如AssemblyFileVersion
,那么我可以按预期读取参数。
完整的代码可以在这里找到: https://github.com/AnderssonPeter/SourceGeneratorAttributes
英文:
I have the following source code generator
[Generator]
public class Generator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var output = @"using System;
namespace SourceGeneratorAttributes;
[AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
class GlobalAttribute : Attribute
{
public int OptionalNumber { get; set; } = 10;
public string OptionalString { get; set; } = ""test"";
public GlobalAttribute(string requiredString, int requiredNumber) {}
}
";
context.AddSource("GlobalAttribute.cs", SourceText.From(output, Encoding.UTF8));
var attributes = context.Compilation.Assembly.GetAttributes();
foreach (var attribute in attributes)
{
Console.WriteLine(attribute);
}
}
public void Initialize(GeneratorInitializationContext context)
{
}
}
Then in the project where I use the source generator I have the following
[assembly:Global("text", 20, OptionalNumber = 33, OptionalString = "random")]
But if I break on Console.WriteLine(attribute);
and inspect the attribute
I get the following:
How do I find what the error is? and why are all arguments gone?
If I use a different attribute like AssemblyFileVersion
then I can read the arguments as expected.
Full code can be found here: https://github.com/AnderssonPeter/SourceGeneratorAttributes
答案1
得分: 0
你需要创建一个单独的类,该类具有实现IIncrementalGenerator
接口并使用RegisterPostInitializationOutput
方法添加Generator
属性。
示例:
[Generator]
public class AttributeGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.RegisterPostInitializationOutput(i =>
{
i.AddSource("GlobalParameterAttribute.g.cs", @"
using System;
namespace SourceGeneratorAttributes;
[AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
public sealed class GlobalParameterAttribute : Attribute
{
public int OptionalNumber { get; set; } = 10;
public string OptionalString { get; set; } = ""test"";
public GlobalParameterAttribute(string requiredString, int requiredNumber) {}
}");
});
}
}
然后,你可以在正常的生成器中使用它,如下所示:
[Generator]
public class Generator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var attributes = context.Compilation.Assembly.GetAttributes();
foreach (var attribute in attributes)
{
Console.WriteLine(attribute);
}
}
public void Initialize(GeneratorInitializationContext context)
{
}
}
英文:
You have to create a separate class that has the Generator
attribute that implements the IIncrementalGenerator
and uses RegisterPostInitializationOutput
to add the attribute
Example:
[Generator]
public class AttributeGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.RegisterPostInitializationOutput(i =>
{
i.AddSource("GlobalParameterAttribute.g.cs", @"using System;
namespace SourceGeneratorAttributes;
[AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
public sealed class GlobalParameterAttribute : Attribute
{
public int OptionalNumber { get; set; } = 10;
public string OptionalString { get; set; } = ""test"";
public GlobalParameterAttribute(string requiredString, int requiredNumber) {}
}");
});
}
}
Then you can use it in your normal generator like so
[Generator]
public class Generator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var attributes = context.Compilation.Assembly.GetAttributes();
foreach (var attribute in attributes)
{
Console.WriteLine(attribute);
}
}
public void Initialize(GeneratorInitializationContext context)
{
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论