欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > 【C# | 分析器】禁止子类在覆写父类虚方法时调用父类方法实现

【C# | 分析器】禁止子类在覆写父类虚方法时调用父类方法实现

2024/10/25 12:24:07 来源:https://blog.csdn.net/qq_21397217/article/details/139968031  浏览:    关键词:【C# | 分析器】禁止子类在覆写父类虚方法时调用父类方法实现

此分析器功能比较简陋,仅作个人备忘。

参考资料:https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix

将以下分析器代码编译为DLL后,将DLL添加到项目分析器列表中,即可进行相关分析。

分析器代码

using System;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;namespace DontCallBaseImplementation
{[AttributeUsage(AttributeTargets.Method, Inherited = false)]public class DontCallBaseImplementationAttribute : Attribute { }[DiagnosticAnalyzer(LanguageNames.CSharp)]public class DontCallBaseImplementationAnalyzer : DiagnosticAnalyzer{public const string DiagnosticId = "DontCallBaseImplementation";private static readonly LocalizableString Title = "Invalid base method implementation call";private static readonly LocalizableString MessageFormat = "Method '{0}' with [DontCallBaseImplementationAttribute] should not call base method implementation";private static readonly LocalizableString Description = "The method in the derived class calls the base method implementation which is marked with [DontCallBaseImplementationAttribute].";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 { get { return ImmutableArray.Create(Rule); } }public override void Initialize(AnalysisContext context){context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);context.EnableConcurrentExecution();context.RegisterSyntaxNodeAction(AnalyzeSyntax, SyntaxKind.InvocationExpression);}private static void AnalyzeSyntax(SyntaxNodeAnalysisContext context){InvocationExpressionSyntax invocationExpression = (InvocationExpressionSyntax)context.Node;if (invocationExpression.Expression is MemberAccessExpressionSyntax memberAccess &&memberAccess.Expression is BaseExpressionSyntax){IMethodSymbol invokedSymbol = context.SemanticModel.GetSymbolInfo(invocationExpression).Symbol as IMethodSymbol;if (invokedSymbol == null) return;IMethodSymbol currentMethod = context.ContainingSymbol as IMethodSymbol;IMethodSymbol baseMethod = currentMethod?.OverriddenMethod;if (!SymbolEqualityComparer.Default.Equals(invokedSymbol, baseMethod)) return;AttributeData dontCallBaseImplAttr = baseMethod.GetAttributes().FirstOrDefault(attr => attr.AttributeClass.Name == nameof(DontCallBaseImplementationAttribute));if (dontCallBaseImplAttr != null){Diagnostic diagnostic = Diagnostic.Create(Rule, invocationExpression.GetLocation(), memberAccess.Name);context.ReportDiagnostic(diagnostic);}}}}
}

添加分析器

在项目的配置文件(csproj)中,添加 ItemGroup 指定分析器引用:

< !--Add to YOUR_PROJECT.csproj-- >
< Project Sdk = "Microsoft.NET.Sdk" >< !--... -->< ItemGroup >< Analyzer Include = "ABSOLUTE_OR_RELATIVE_FOLDER\DontCallBaseImplementation.dll" /></ ItemGroup >< !--... --></ Project >

代码中的使用方法

定义一个 DontCallBaseImplementationAttribute 类(也可以直接使用分析器DLL中提供的同名类,但要为项目添加对DLL的依赖项):

[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class DontCallBaseImplementationAttribute : Attribute { }

在不希望子类覆写时调用父类方法实现的虚方法上,添加上述特性:

class BaseClass
{[DontCallBaseImplementation]public virtual void DoSomething(){Console.WriteLine("BaseClass.DoSomething()");}
}

之后,若子类重写方法时调用了父类方法实现,编辑器会报告错误:

class DerivedClass : BaseClass
{public override void DoSomething(){base.DoSomething(); // Will report an error}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com