是否有一种方法可以确保标记为[AttributeUsage(AttributeTargets.Property)]的属性在每个类中最多使用一次?换句话说,0或1属性都应该用特定的属性修饰,不能超过1。这能做到吗?
[AttributeUsage(AttributeTargets.Property)]
13z8s7eq1#
您可以创建自己的分析器,将其编译成dll并包含在您的项目中。让我们从“测试”开始,以确保一切都如您所期望的那样工作:单个属性类编译x1c 0d1x第二个属性-类不编译
第二种属性类型-不同的属性一起工作并编译
属性是独立计数的-如果其中任何一个在类中存在多次,则不会编译。
分析器错误消息x1c4d 1x下面是分析器代码。它遍历了csharp语法,对带有标记为AttributeUsageAttribute且具有标志AttributeTargets.Property的属性的属性进行计数
AttributeUsageAttribute
AttributeTargets.Property
using System.Collections.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; [DiagnosticAnalyzer(LanguageNames.CSharp)] public class PropertyAttributeAnalyzer : DiagnosticAnalyzer { private const string Category = "Usage"; private static DiagnosticDescriptor Rule = new DiagnosticDescriptor( "PA001", "Multiple Properties with Attribute", "Multiple properties with the attribute '{0}' are found in the class", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) { context.RegisterSyntaxNodeAction(AnalyzeClassSyntax, SyntaxKind.ClassDeclaration); } private static void AnalyzeClassSyntax(SyntaxNodeAnalysisContext context) { var classDeclaration = (ClassDeclarationSyntax)context.Node; var occurrences = new Dictionary<string, int>(); foreach (var property in classDeclaration.Members.OfType<PropertyDeclarationSyntax>()) { var attributes = property.AttributeLists.SelectMany(list => list.Attributes); foreach (var attribute in attributes) { if (!IsDesiredAttribute(context, classDeclaration, attribute)) continue; if (occurrences.ContainsKey(attribute.Name.ToString())) { occurrences[attribute.Name.ToString()]++; } else { occurrences[attribute.Name.ToString()] = 1; } } } foreach (var attribute in occurrences.Where(x => x.Value > 1)) { var diagnostic = Diagnostic.Create(Rule, classDeclaration.Identifier.GetLocation(), attribute.Key); context.ReportDiagnostic(diagnostic); } } private static bool IsDesiredAttribute(SyntaxNodeAnalysisContext context, ClassDeclarationSyntax classDeclaration, AttributeSyntax attributeSyntax) { var semanticModel = context.SemanticModel; var attributeSymbol = semanticModel.GetSymbolInfo(attributeSyntax).Symbol; var attributeType = attributeSymbol?.ContainingType; if (attributeType is null) return false; var attributeUsageAttribute = semanticModel.Compilation.GetTypeByMetadataName(typeof(AttributeUsageAttribute).FullName); var attributeUsage = attributeType.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Equals(attributeUsageAttribute)); if (attributeUsage is null) return false; var validOnArgument = attributeUsage.ConstructorArguments.FirstOrDefault(arg => arg.Type?.Name == "AttributeTargets"); var validTargets = (AttributeTargets)(int)validOnArgument.Value; return validTargets.HasFlag(AttributeTargets.Property); } }
您必须编译Analyzer并将其dll链接到项目的csproj文件中
<ItemGroup> <Analyzer Include="C:\Users\Asus\RiderProjects\TestAnalyzer\Analyzer\bin\Debug\net7.0\Analyzer.dll"/> </ItemGroup>
最后,我的解决方案结构
1条答案
按热度按时间13z8s7eq1#
您可以创建自己的分析器,将其编译成dll并包含在您的项目中。
让我们从“测试”开始,以确保一切都如您所期望的那样工作:
单个属性类编译x1c 0d1x
第二个属性-类不编译
第二种属性类型-不同的属性一起工作并编译
属性是独立计数的-如果其中任何一个在类中存在多次,则不会编译。
分析器错误消息x1c4d 1x
下面是分析器代码。它遍历了csharp语法,对带有标记为
AttributeUsageAttribute
且具有标志AttributeTargets.Property
的属性的属性进行计数您必须编译Analyzer并将其dll链接到项目的csproj文件中
最后,我的解决方案结构