You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何确保标记[AttributeUsage(AttributeTargets.Property)]的属性在类中仅修饰单个属性?

如何确保自定义属性在每个类的属性上最多使用一次?

可以实现,主要有编译时验证和运行时检查两种方案,其中编译时验证能在开发阶段提前发现问题,是更推荐的方式。

编译时验证(推荐)

通过Roslyn分析器在编译阶段做检查,直接在IDE或编译过程中报错,避免问题留到运行时。

实现思路

创建一个Roslyn分析器项目,遍历每个类的属性,统计被目标自定义属性标记的数量,一旦超过1就触发诊断提示。

简化示例代码

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class SinglePropertyAttributeAnalyzer : DiagnosticAnalyzer
{
    public const string DiagnosticId = "SinglePropertyAttribute";
    private static readonly LocalizableString Title = "多个属性标记了[YourCustomAttribute]";
    private static readonly LocalizableString MessageFormat = "类'{0}'中有{1}个属性标记了[YourCustomAttribute]; 最多允许一个";
    private static readonly LocalizableString Description = "每个类最多只能有一个属性被[YourCustomAttribute]标记。";
    private const string Category = "Usage";

    private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
        DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Error, isEnabledByDefault: true, description: Description);

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);

    public override void Initialize(AnalysisContext context)
    {
        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
        context.EnableConcurrentExecution();

        context.RegisterSymbolAction(AnalyzeClass, SymbolKind.NamedType);
    }

    private void AnalyzeClass(SymbolAnalysisContext context)
    {
        var classSymbol = (INamedTypeSymbol)context.Symbol;
        if (classSymbol.TypeKind != TypeKind.Class) return;

        int attributeCount = 0;
        foreach (var property in classSymbol.GetMembers().OfType<IPropertySymbol>())
        {
            if (property.GetAttributes().Any(attr => attr.AttributeClass?.Name == "YourCustomAttribute"))
            {
                attributeCount++;
                if (attributeCount > 1)
                {
                    var diagnostic = Diagnostic.Create(Rule, property.Locations[0], classSymbol.Name, attributeCount);
                    context.ReportDiagnostic(diagnostic);
                }
            }
        }
    }
}

将YourCustomAttribute替换成你实际的自定义属性名称即可,这个分析器会在编译时拦截违规代码,直接给出错误提示。

运行时检查

如果不想开发Roslyn分析器,也可以通过反射在运行时做验证,比如在应用启动阶段扫描所有类。

实现示例

public static void ValidateSinglePropertyAttribute(Type type)
{
    var markedProperties = type.GetProperties()
        .Where(p => p.GetCustomAttributes(typeof(YourCustomAttribute), inherit: false).Any())
        .ToList();

    if (markedProperties.Count > 1)
    {
        throw new InvalidOperationException($"类 {type.FullName} 中有 {markedProperties.Count} 个属性标记了[YourCustomAttribute]; 最多允许一个。");
    }
}

// 应用启动时执行检查
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
    foreach (var type in assembly.GetTypes())
    {
        ValidateSinglePropertyAttribute(type);
    }
}

这种方式的缺点是问题只能在运行时暴露,适合小型项目或临时验证场景。

注意

AttributeUsage的AllowMultiple参数仅控制同一个属性上是否允许多次应用该自定义属性,无法限制同一个类中多个属性使用该属性,因此必须借助上述方案实现需求。

内容的提问来源于stack exchange,提问作者cogumel0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:38:30