ASP .Roslynアナライザとネットコアミドルウェア-パート1


ASP .ASP . NETコアミドルウェアは、ASPで認証、ルーティング、およびエラーログのような機能を設定する巧妙な方法です.ネットコア.しかし、ミドルウェアの異なる部分を追加し、正しい順序ではかなり悪夢をすることができます.このポストでは、私はどのようにroslynアナライザを助けることができるかを紹介します.
ミドルウェアは、文字列の真珠のように動作します.ミドルウェアを追加すると、ミドルウェアは最初に呼ばれ、最後に呼ばれます.これは重大な問題を引き起こす可能性があります.エラーが発生していることを通知されないミドルウェアのようなエラーログです.問題はすでにアンドリューロックのInserting middleware between UseRouting() and UseEndpoints() as a library author - Part 1 and Part 2 , それで、あなたがすでにあなたのプロジェクトで痛みを感じたならば、それらを通して読むようにしてください.
私は、エルマハを助けるために、ロスランAnalerzerのカップルをつくりたかったです.IOユーザは、呼び出しを挿入しますUseElmahIo そして、適切な場所で.AnalyzerはVisual Studioの中で実行されているC - Countコードの小さな部分で、プロジェクトソースコードを解析し、Visual Studioのエラーリストウィンドウに任意の問題を報告します.
新しいRoslyn Analyzerを作成するには、最も簡単なアプローチは、Visual Studioで既に使用可能なテンプレートに基づいています.新しいプロジェクトを作成し、コード修正プログラム(. NET Standard)テンプレートを使用してアナライザを選択します.これは、makeconstアナライザとコード修正プログラムで新しいプロジェクトを生成します.このデモのための新しいものを作成するので、2つのC経線ファイルを削除することができます.
の検証を開始しましょうUseElmahIo メソッドはConfigure メソッドStartup.cs ファイル.私は、新しいCチェックインクラスを作成していますCallUseElmahIoAnalyzer.cs . 私は、基本的な構造をMakeConst 以前にアナライザ
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class CallUseElmahIoAnalyzer : DiagnosticAnalyzer
{
    public const string DiagnosticId = "EIO1001";

    private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(
        DiagnosticId,
        "Configure must call UseElmahIo",
        "Configure must call UseElmahIo",
        "Elmah.Io.CSharp.AspNetCoreRules",
        DiagnosticSeverity.Warning,
        isEnabledByDefault: true);

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

    public override void Initialize(AnalysisContext context)
    {
    }
}
気づくべきことがいくつかあります.アナライザは、宣言して、広げますDiagnosticAnalyzer クラス.これは、Visual Studioが自動的に一度VSX(Visual Studio拡張)としてインストールされてアナライザを拾うようになります.アナライザーのメタデータはDiagnosticDescriptor そして、ID、メッセージをユーザーに表示するだけでなく、他のカップルのカップルが含まれます.The Initialize 方法は魔法が起こるところです.
アナライザは、ビジターパターンを使用して実装されます.あなたが興味のあるコードの部分のハンドラーを登録し、Roslynは分析のもとで自動的にソースコードを解析し、コードをメタデータで提供します.コードは少し奇妙に見えるかもしれませんが、最初に設計されたが、一度モデルと知り合いになるとかなり強力になります.
この最初の分析器のためにConfigure メソッド呼び出しUseElmahIo メソッド.この簡単な例については、呼び出しを名前Configure クラスでStartup :
public override void Initialize(AnalysisContext context)
{
    context.RegisterCodeBlockStartAction<SyntaxKind>(cb =>
    {
        // We only care about method bodies.
        if (cb.OwningSymbol.Kind != SymbolKind.Method) return;
        var method = (IMethodSymbol)cb.OwningSymbol;
        // We only care about methods named ConfigureServices
        if (method.Name != "Configure") return;
        if (method.ContainingType.Name != "Startup") return;
    });
}
そのための行動RegisterCodeBlocStartAction メソッドは、新しいコードブロックが始まるたびにRoslynによって呼び出されます.コードブロックは、クラス、フィールド、メソッドなど、メタデータを検査することによって、現在のコールバックが既に言及している要件を満たさない場合には、その例を返します.
を返します.if ステートメントは、我々は現在、内部の知っているConfigure メソッド.Roslynは入れ子になった構文動作を許します.なぜ新しいコールバックを登録できるのでしょうか
public override void Initialize(AnalysisContext context)
{
    context.RegisterCodeBlockStartAction<SyntaxKind>(cb =>
    {
        // the code from the previous example

        bool useElmahIoInvocationFound = false;

        cb.RegisterSyntaxNodeAction(ctx =>
        {
            var node = ctx.Node as InvocationExpressionSyntax;
            if (node == null) return;
            var expression = node.Expression as MemberAccessExpressionSyntax;
            if (expression == null) return;
            var methodName = expression.Name?.Identifier.ValueText;
            if (methodName == "UseElmahIo") useElmahIoInvocationFound = true;
        }, SyntaxKind.InvocationExpression);
    });
}
新しいコードは、構文ノードのアクションを登録し、Configure 指定するSyntaxKind.InvocationExpression パラメータとしてRegisterSyntaxNodeAction メソッド).各構文ノードで、メソッド呼び出しであるかどうかをチェックしますUseElmahIo . 我々が呼び出しを見つける場合UseElmahIo 私たちはuseElmahIoInvocationFound trueにboolean.
最後の行方不明は、エンドアクションを登録することです.使用する場合RegisterCodeBlockStartAction メソッドでは、メソッドの意味解析の終了時にログリンを呼び出してコールバックを指定する必要がありますConfigure ). 混乱?コードを見てみましょう.
public override void Initialize(AnalysisContext context)
{
    context.RegisterCodeBlockStartAction<SyntaxKind>(cb =>
    {
        // the code from the previous example

        cb.RegisterCodeBlockEndAction(ctx =>
        {
            if (!useElmahIoInvocationFound)
            {
                var diag = Diagnostic.Create(Rule, method.Locations[0]);
                ctx.ReportDiagnostic(diag);
            }
        });
    });
}
場合にはuseElmahIoInvocationFound booleanはfalse 我々はReportDiagnostic Visual Studio内で警告を表示する方法です.警告に使用するメタデータをRule 我々がすでに議論したフィールドと同様にConfigure メソッド.
全体を見ましょうInitialize メソッド:
public override void Initialize(AnalysisContext context)
{
    context.RegisterCodeBlockStartAction<SyntaxKind>(cb =>
    {
        // We only care about method bodies.
        if (cb.OwningSymbol.Kind != SymbolKind.Method) return;
        var method = (IMethodSymbol)cb.OwningSymbol;
        // We only care about methods named ConfigureServices
        if (method.Name != "Configure") return;
        if (method.ContainingType.Name != "Startup") return;

        bool useElmahIoInvocationFound = false;

        cb.RegisterSyntaxNodeAction(ctx =>
        {
            var node = ctx.Node as InvocationExpressionSyntax;
            if (node == null) return;
            var expression = node.Expression as MemberAccessExpressionSyntax;
            if (expression == null) return;
            var methodName = expression.Name?.Identifier.ValueText;
            if (methodName == "UseElmahIo") useElmahIoInvocationFound = true;
        }, SyntaxKind.InvocationExpression);

        cb.RegisterCodeBlockEndAction(ctx =>
        {
            if (!useElmahIoInvocationFound)
            {
                var diag = Diagnostic.Create(Rule, method.Locations[0]);
                ctx.ReportDiagnostic(diag);
            }
        });
    });
}
新しい分析器をテストするには、起動プロジェクトとしてVsixプロジェクトを設定し、F 5を押すようにしてください.これはVisual Studioの実験例を開始します.新しいASPを作成します.NETコアプロジェクトまたは既存のものを開き、Startup クラス.もしUseElmahIo 呼び出しが行われると、Visual Studioで直接警告が表示されます.

新しいアナライザを配布するには、生成されたVSixファイルをVisual Studio Marketplaceにアップロードするか、Analyzerを含むプロジェクトをNugetパッケージとして発行します.
それだ!ここでは、ミドルウェアの正しい順序を検証するアナライザーを作成して、その例を続けます.Elmahのための完全なソースコード.のためのIOロスリンアナライザ.NETコアはここで見つかります.https://github.com/elmahio/Elmah.Io.AspNetCore.Analyzers

あなたのユーザーは、より少しの誤りを評価しますか?


エルマ.IOは簡単なエラーログとアップタイム監視サービスです.ネットすべてのサポートを使用してエラーのコントロールを取り戻す.NET Webおよびログフレームワーク.
➡️ Error Monitoring for .NET Web Applications ⬅️
この記事はエルマに初めて現れた.ioのブログhttps://blog.elmah.io/asp-net-core-middleware-with-roslyn-analyzers-part-1/