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

如何在C#中创建自定义ObsoleteAttribute以触发使用时编译警告

自定义带固定消息的“过时”编译警告需求

我希望复用固定的过时提示消息,避免在每个ObsoleteAttribute中重复编写相同内容。于是我自定义了如下属性:

[AttributeUsage(AttributeTargets.Property)]
public class MyObsoleteAttribute : Attribute
{
    private const string CustomMessage = "This is a custom warning message";
    public MyObsoleteAttribute()
    {
        Console.WriteLine(CustomMessage);
    }
}
    
public class MyClass
{
    [MyObsolete]
    public string? Foo { get; set; }
    
    [MyObsolete]
    public string? Bar { get; set; }
    
    [MyObsolete]
    public string? FooBar { get; set; }
}

但原生ObsoleteAttribute是sealed无法继承,导致使用标记了MyObsoleteAttribute的属性时,无法像原生Obsolete那样触发编译警告。比如以下代码应该触发警告,但目前没有任何提示:

var myClass = new MyClass();
var foo = myClass.Foo;
var bar = myClass.Bar;
var fooBar = myClass.FooBar;

解决方案

方案一:Roslyn分析器(跨VS/Rider,编译级警告)

通过编写Roslyn分析器,可以在编译阶段检测到标记了MyObsoleteAttribute的成员使用,并触发自定义警告。

步骤1:创建分析器项目

创建一个.NET Standard类库,安装以下NuGet包:

  • Microsoft.CodeAnalysis.Analyzers
  • Microsoft.CodeAnalysis.CSharp

步骤2:编写分析器代码

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;
using System.Linq;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class MyObsoleteAnalyzer : DiagnosticAnalyzer
{
    // 自定义诊断ID,可自行修改
    public const string DiagnosticId = "MYOBSOLETE001";
    private const string Category = "Usage";

    // 自定义警告消息
    private const string WarningMessage = "This is a custom warning message";
    private static readonly LocalizableString Title = "使用了过时成员";
    private static readonly LocalizableString MessageFormat = "成员 '{0}' 已过时:" + WarningMessage;
    private static readonly LocalizableString Description = "访问了标记为MyObsolete的成员";

    private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
        DiagnosticId, Title, MessageFormat, Category,
        DiagnosticSeverity.Warning, 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.RegisterSyntaxNodeAction(AnalyzeMemberAccess, SyntaxKind.SimpleMemberAccessExpression);
    }

    private void AnalyzeMemberAccess(SyntaxNodeAnalysisContext context)
    {
        var memberAccess = (MemberAccessExpressionSyntax)context.Node;
        var symbol = context.SemanticModel.GetSymbolInfo(memberAccess.Name).Symbol as IPropertySymbol;

        if (symbol == null) return;

        // 检查当前属性是否标记了MyObsoleteAttribute
        var hasMyObsoleteAttr = symbol.GetAttributes()
            .Any(attr => attr.AttributeClass?.Name == nameof(MyObsoleteAttribute));

        if (hasMyObsoleteAttr)
        {
            // 触发警告
            var diagnostic = Diagnostic.Create(Rule, memberAccess.Name.GetLocation(), symbol.Name);
            context.ReportDiagnostic(diagnostic);
        }
    }
}

步骤3:使用分析器

将分析器项目引用到目标项目,或者打包成NuGet包安装。此后编译项目时,只要访问标记了MyObsolete的属性,就会触发自定义警告。


方案二:JetBrains Rider自定义配置(仅Rider生效)

如果仅在Rider环境下开发,可以直接通过IDE配置让MyObsoleteAttribute被识别为过时标记:

  1. 打开Rider设置(Ctrl+Alt+S)
  2. 导航到Inspections > C# > Code style issues > Obsolete symbol usage
  3. 在右侧面板找到Custom obsolete attributes,点击Add
  4. 输入MyObsoleteAttribute的完整类型名(例如YourNamespace.MyObsoleteAttribute)
  5. 在下方Message栏输入固定警告消息:This is a custom warning message
  6. 保存设置后,Rider会在使用标记了MyObsolete的属性时,自动显示与原生Obsolete一致的警告提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 22:15:33