2017-08-04 83 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