Dot.Blog

Consulting DotNet C#, XAML, WinUI, WPF, MAUI, IA

Créer un analyseur Roslyn pour valider automatiquement du code métier

Les analyseurs Roslyn permettent d’ajouter des règles de validation personnalisées lors de la compilation. Cela peut s’avérer particulièrement utile pour faire respecter des conventions métier, éviter des pièges récurrents ou guider les développeurs d’une équipe.

Dans cet article, nous allons créer un analyseur simple qui interdit l’appel direct à DateTime.Now, en forçant l’usage d’un service d’abstraction du temps.

🛠️ Prérequis

  • Visual Studio 2022+ avec le workload « Développement .NET »
  • SDK .NET 9+
  • Modèle de projet « Analyseur de code C# » (VSIX ou bibliothèque classique)

🧱 Étape 1 – Créer le projet d’analyseur

  1. Nouveau projet > Rechercher « analyseur »
  2. Choisir Bibliothèque d’analyseurs C#
  3. Nommer : NoDateTimeNowAnalyzer

Cela génère deux projets :

  • NoDateTimeNowAnalyzer : l’analyseur lui-même
  • NoDateTimeNowAnalyzer.Test : les tests unitaires avec xUnit + infrastructure Roslyn

🧩 Étape 2 – Écrire une règle d’analyse

Dans NoDateTimeNowAnalyzer.cs :

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class NoDateTimeNowAnalyzer : DiagnosticAnalyzer
{
    public const string DiagnosticId = "NODATENOW";
    private static DiagnosticDescriptor Rule = new(
        DiagnosticId,
        "Éviter DateTime.Now",
        "L'appel à DateTime.Now est interdit : utilisez IClock",
        "Conventions métier",
        DiagnosticSeverity.Warning,
        isEnabledByDefault: true);

   public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Rule];

    public override void Initialize(AnalysisContext context)
    {
        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
        context.EnableConcurrentExecution();
        context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.SimpleMemberAccessExpression);
    }

    private void AnalyzeNode(SyntaxNodeAnalysisContext context)
    {
        var memberAccess = (MemberAccessExpressionSyntax)context.Node;
        if (memberAccess.ToString() == "DateTime.Now")
        {
            var diagnostic = Diagnostic.Create(Rule, memberAccess.GetLocation());
            context.ReportDiagnostic(diagnostic);
        }
    }
}

🧪 Étape 3 – Tester l’analyseur

Dans le projet de test généré :

[Fact]
public async Task DateTimeNow_ProvoqueAlerte()
{
    var code = """
        class TestClass {
            void Test() {
                var t = DateTime.Now;
            }
        }
    """;
    var expected = Verify.Diagnostic("NODATENOW").WithSpan(4, 26, 4, 40);
    await Verify.VerifyAnalyzerAsync(code, expected);
}

Utilisez VerifyCS de Microsoft.CodeAnalysis.CSharp.Testing.XUnit pour simplifier les tests.

🧪 Étape 4 – Intégration dans un projet réel

Référencez le projet ou package NuGet généré par votre analyseur dans un projet de production. Le warning apparaîtra automatiquement dans l’IDE et à la compilation.

✅ Conclusion

Créer un analyseur Roslyn permet de personnaliser les règles de compilation pour faire respecter vos standards internes, notamment métier. Cet exemple peut être adapté pour interdire d'autres usages ou guider les développeurs vers de meilleures pratiques.

Stay Tuned !

Faites des heureux, PARTAGEZ l'article !