Making extension methods from a third party library obsolete
这个问题不是关于我可以用[System.Obsolete]标记的方法。我要忽略的方法在一个我无法控制的dll中。
我使用包含对象扩展方法的第三方库。这会导致混乱,并可能在将来引起问题。是否有任何方法可以将此扩展方法(或来自某个dll的所有扩展方法)标记为外部过时,或阻止此扩展方法在IntelliSense中出现。有问题的方法是:
1 2 3 4 5 6 7 8 9 |
您可以使用Roslyn代码分析器来实现这一点。下面的代码将创建一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | [DiagnosticAnalyzer(LanguageNames.CSharp)] public class ForbiddenMethodsAnalyzer : DiagnosticAnalyzer { private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor("Forbidden", "Don't use this method!", "Use of the '{0}' method is not allowed", "Forbidden.Stuff", DiagnosticSeverity.Warning, isEnabledByDefault: true, description:"This method is forbidden"); public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } } public override void Initialize(AnalysisContext context) { context.RegisterSyntaxNodeAction(AnalyzeSyntaxNode, SyntaxKind.InvocationExpression); } private static void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) { var invocationExpression = (InvocationExpressionSyntax)context.Node; var memberAccessExpression = invocationExpression.Expression as MemberAccessExpressionSyntax; if (memberAccessExpression?.Name.ToString() =="EndsWith") { var memberSymbol = context.SemanticModel.GetSymbolInfo(memberAccessExpression).Symbol as IMethodSymbol; var containingType = memberSymbol.ContainingType; if (containingType.ContainingNamespace.Name =="System" && containingType.Name =="String") { var diagnostic = Diagnostic.Create(Rule, invocationExpression.GetLocation(), memberAccessExpression.ToString()); context.ReportDiagnostic(diagnostic); } } } } |
使用这样的分析器有3个选项:
- 直接将
DiagnosticAnalyzer 代码添加到项目中。它只适用于该解决方案。 - 创建一个包含
DiagnosticAnalyzer 的类库,并分发作为Nuget包。它只适用于使用该包的解决方案。 - 编译包含班级。分析器将处理您加载的任何解决方案。
这是我所做的第一个使用Roslyn代码分析功能的项目,因此很遗憾我不了解这里发生的一切。我从默认的分析器模板开始,尝试了各种方法,逐步执行代码,并使用监视窗口查看变量,直到找到实现此功能所需的信息。
基本过程是注册一个syntaxnode分析函数,过滤到调用方法的表达式。在这种方法中,我检查被检查的
本教程提供了大量信息,以及大量的尝试和错误。
处理这种情况的最佳方法是使用Roslyn并创建自己的代码分析器,或者使用现有的工具(如fxcop)。
然而,我发现了一个非常不优雅的解决方法。
在项目中,可以使用完全相同的方法创建与被引用类同名的类,该类位于相同的命名空间中。现在将您的方法标记为已过时。
下面的代码示例引用了在
使用此解决方案,如果使用扩展方法语法,则可以从引用的类型调用其他扩展方法,前提是类中没有定义相同的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | using System; using External; namespace Internal { class Program { static void Main(string[] args) { ExtensionMethods.IsNumeric(new object()); // (*) new object().IsNumeric(); // (**) } } } namespace External { public static class ExtensionMethods { [Obsolete] public static bool IsNumeric(this object o) { if (obj == null) return false; return obj.GetType().IsPrimitive || obj is double || (obj is Decimal || obj is DateTime) || obj is TimeSpan; } } } |