2017-08-04 41 views
5

这个问题是而不是关于我可以用[System.Obsolete]标记的方法。我想忽略的方法是在一个dll中,我无法控制。使第三方库的扩展方法变得过时

我使用包含对象扩展方法的第三方库。这会导致混淆,并可能在将来导致问题。 有什么办法可以将这个扩展方法(或某个特定dll的所有扩展方法)标记为外部过时或防止这种扩展方法出现在intellisense中。该问题的方法是:

public static class ExtensionMethods 
    { 
     public static bool IsNumeric(this object obj) 
     { 
     if (obj == null) 
      return false; 
     return obj.GetType().IsPrimitive || obj is double || (obj is Decimal || obj is DateTime) || obj is TimeSpan; 
     } 
    } 
+0

它是否在您可以安全忽略的名称空间中? –

+0

@ DanielA.White是的,但我只想忽略扩展方法,不是整个DLL或命名空间 – yey

+1

链接的问题是否真的重复?这个问题是关于在你自己的程序集中标记一个你控制的方法。这个问题是关于在第三方程序集中标记的,你无法控制。我已投票重新开放。 –

回答

4

来处理这种情况的最好方法是使用罗斯林和创建自己的代码分析仪,或使用像FxCop的现有工具。

但是,我发现了一个非常不雅的解决方法。

在您的项目中,您可以使用完全相同的方法创建一个与被引用类相同名称的类,它位于相同的名称空间中。现在将您的方法标记为过时。

下面的代码示例有一个对ExtensionMethods类的库的引用,该类在External命名空间中定义。在标注为(*)注释的行中,使用静态方法调用语法调用该方法时,编译器会警告您类型ExtensionMethods与导入的类型冲突。它也告诉你方法已过时(因为你已经隐藏了导入的类型,它看到了你的定义)。所以当你调用这个方法时,你的代码将会运行。在标有(**)评论的行中,如果使用扩展方法调用语法调用方法,编译器会说调用不明确,代码将不会编译。我所知道的唯一解决方法是将此呼叫转变为行(*),这将产生过时的警告。

使用此解决方案,如果您使用扩展方法语法,您将能够从引用类型调用其他扩展方法,前提是您没有在类中定义相同的方法。

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; 
     } 
    } 
} 
4

您可以使用Roslyn Code Analyzer做到这一点。以下代码将创建一个DiagnosticAnalyzer,如果使用String.EndsWith(),将会发出编译器警告。

[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); 
      } 
     } 
    } 
} 

Tooltip warning Error List warning

有3个选项,使用分析是这样的:

  • 直接添加DiagnosticAnalyzer代码到您的项目。它将仅适用于该解决方案。
  • 创建一个 类库,其中包含DiagnosticAnalyzer,并将其作为Nuget包分发给 。它仅适用于使用该软件包的解决方案。
  • 编译包含 类的完整VSIX扩展。分析仪可以在您加载的任何解决方案上工作。

这是我使用Roslyn代码分析功能所做的第一个项目,所以很不幸我不明白这里发生的一切。我开始使用默认的分析模板,并尝试了各种方法,遍历代码,并使用监视窗口查看变量,直到找到所需的信息为止。

基本过程是注册一个SyntaxNode分析函数,过滤到调用方法的表达式。在该方法中,我检查MemberAccessExpressionSyntaxName是否是“EndsWith”。如果是,则获取方法处于打开状态的ContainingType,然后检查它是否位于System命名空间的String类中。如果是这样,我从DiagnosticDescriptor创建一个Diagnostic实例来告诉IDE问题出在哪里以及它代表了多少问题(在这种情况下有一个警告,如果我愿意,可以将它设置为一个完整的错误,这将防止来自编译的代码)。也可以向用户提供不同的选项来自动修复错误,但我还没有探究过。

很多信息来自this tutorial,以及大量的试验和错误。

+0

如果您可以访问Pluralsight,他们有一个非常好的课程,称为* .NET编译器平台简介*。这里有点过时了,但它并没有减少它的用处。 – Kapol

+0

您可能想补充说,如果严格禁止使用该方法,则可以更改严重性以使代码不可编译。 – Kapol