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

如何在VS中自定义编译前规则,强制调用自定义类的MyEndMethod?

实现自定义编译规则强制调用MyEndMethod()

方案:使用Roslyn分析器

Roslyn是.NET官方编译器平台,可编写自定义代码分析器,在编译阶段检查代码合规性,不符合规则直接抛出编译错误,完全匹配你的需求,无需依赖IDisposable接口。

步骤1:创建Roslyn分析器项目

在Visual Studio中操作:

  • 新建项目,搜索**"Analyzer with Code Fix (.NET Standard)"**模板,选中后创建项目。
  • 项目会自动生成默认分析器类,基于此修改即可。

步骤2:编写分析器逻辑

替换默认分析器代码为以下内容,实现Myclass实例创建后必须调用MyEndMethod()的检测:

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

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class MyClassEndMethodAnalyzer : DiagnosticAnalyzer
{
    // 定义诊断标识、提示信息等内容
    public const string DiagnosticId = "MYCLASS001";
    private const string Title = "必须调用MyEndMethod()";
    private const string MessageFormat = "Myclass实例 '{0}' 使用后未调用MyEndMethod()";
    private const string Description = "创建Myclass实例后,必须调用其MyEndMethod()方法";
    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.EnableConcurrentExecution();
        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

        // 注册对方法体的分析逻辑
        context.RegisterSyntaxNodeAction(AnalyzeMethodBody, SyntaxKind.MethodDeclaration);
    }

    private void AnalyzeMethodBody(SyntaxNodeAnalysisContext context)
    {
        var methodDeclaration = (MethodDeclarationSyntax)context.Node;
        var methodBody = methodDeclaration.Body;
        if (methodBody == null) return;

        // 收集当前方法内所有Myclass的实例声明
        var myClassDeclarations = methodBody.DescendantNodes()
            .OfType<VariableDeclarationSyntax>()
            .Where(vd => vd.Type.ToString() == "Myclass")
            .SelectMany(vd => vd.Variables)
            .ToDictionary(v => v.Identifier.Text);

        if (myClassDeclarations.Count == 0) return;

        // 收集当前方法内所有调用了MyEndMethod()的实例名称
        var endMethodCalls = methodBody.DescendantNodes()
            .OfType<InvocationExpressionSyntax>()
            .Where(ie => ie.Expression is MemberAccessExpressionSyntax mae 
                         && mae.Name.Identifier.Text == "MyEndMethod"
                         && mae.Expression is IdentifierNameSyntax ins
                         && myClassDeclarations.ContainsKey(ins.Identifier.Text))
            .Select(ie => ((MemberAccessExpressionSyntax)ie.Expression).Expression)
            .OfType<IdentifierNameSyntax>()
            .Select(ins => ins.Identifier.Text)
            .ToHashSet();

        // 检查每个Myclass实例是否调用了MyEndMethod(),未调用则触发编译错误
        foreach (var (varName, varDecl) in myClassDeclarations)
        {
            if (!endMethodCalls.Contains(varName))
            {
                var diagnostic = Diagnostic.Create(Rule, varDecl.GetLocation(), varName);
                context.ReportDiagnostic(diagnostic);
            }
        }
    }
}

步骤3:生成并引用分析器包

  • 右键分析器项目,选择**"Pack"**,生成NuGet包(.nupkg格式文件)。
  • 在你的.NET Framework项目中,添加这个本地NuGet包的引用。

效果验证

当你创建Myclass实例但未调用MyEndMethod()时,Visual Studio会实时显示错误波浪线,编译阶段直接报错并阻止项目生成,错误提示为我们定义的内容。

补充说明

  • 上述代码实现了基础检测逻辑:同一方法内创建的Myclass实例必须调用MyEndMethod()。若需支持实例作为参数传递、返回值等复杂场景,可扩展分析逻辑跟踪实例数据流。
  • 若无需打包NuGet,也可直接将分析器项目作为项目引用添加到目标.NET Framework项目中,同样能生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 08:15:35