我有一个 .NET 5 源生成器,我正在尝试可靠地检测已标记为特定属性的类,该属性已作为同一生成器的一部分生成。
问题是我找不到合适的方法来比较这些类型 - 我尝试了一系列不同的选项,但没有一个适用于所有场景。
在我的生成器中,我正在生成这样的属性:
[Generator]
public sealed class AddAttribute1 : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context) { }
public void Execute(GeneratorExecutionContext context)
{
var code = @"
using System;
namespace DependencyReproGenerator.Library.Attributes
{
[AttributeUsage(AttributeTargets.Class)]
public sealed class CustomAttribute1Attribute : Attribute
{
public CustomAttribute1Attribute() { }
}
}";
context.AddSource("CustomAttribute1Attribute.generator", SourceText.From(code, Encoding.UTF8));
}
}
在另一个项目中,我引用源生成器,并使用如下属性:
using DependencyReproGenerator.Library.Attributes;
namespace DependencyRepro
{
[CustomAttribute1]
public class Class1
{
}
}
到目前为止,一切都很好。当我添加另一个源生成器时,ISyntaxContextReceiver
在初始化期间使用 an ,我试图检查访问的节点是否具有此属性,这就是我正在努力的地方。
这是我的ISyntaxContextReceiver
:
class ConstructorGeneratorReceiver : ISyntaxContextReceiver
{
public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
{
if (context.Node is ClassDeclarationSyntax classDeclarationSyntax)
{
foreach (AttributeSyntax attribute in classDeclarationSyntax
.DescendantNodes().OfType<AttributeSyntax>())
{
SyntaxToken lastDescendantToken = attribute.DescendantTokens()
.Where(p => p.IsKind(SyntaxKind.IdentifierToken)).Last();
ITypeSymbol lastDescendantTokenType =
context.SemanticModel.GetTypeInfo(lastDescendantToken.Parent).Type;
ITypeSymbol lastDescendantConvertedTokenType =
context.SemanticModel.GetTypeInfo(lastDescendantToken.Parent).ConvertedType;
// TODO: Compare something against the expected type
}
}
}
}
我知道我可以比较类型的名称(例如,lastDescendantTokenType.Name == "CustomAttribute1"
),但我知道如果另一个具有相同名称的属性存在于不同的命名空间中,它也会选择那个,所以理想情况下,我想要还要比较类型的命名空间。
如何检查当前的 ClassDeclarationSyntax 节点是否具有特定属性(包括属性名称和命名空间的匹配)?