L'attribut InternalsVisibleTo est un outil essentiel dans l'écosystème .NET, permettant à des types internes (par défaut non accessibles depuis l'extérieur de leur assembly) d'être exposés et consommés par des assemblies spécifiques. Cette fonctionnalité est particulièrement utile dans les scénarios de tests unitaires, où il est souvent nécessaire de tester des composants internes sans les rendre publics à l'ensemble de l'application.
Déclaration Traditionnelle de l'Attribut
Historiquement, l'attribut InternalsVisibleTo était souvent déclaré dans le fichier AssemblyInfo.cs ou directement dans un fichier source C# de l'assembly cible, en utilisant la syntaxe suivante :
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MonProjet.Tests")]
Cette approhce est simple pour un projet unique, mais elle devient fastidieuse lorsque l'on gère une solution composée de nombreux projets, chacun nécessitant sa propre déclaration pour son projet de tests associé. Chaque fichier projet doit être modifié manuellement, ce qui introduit une maintenance répétitive.
Intégration via le Fichier Projet (CSPROJ)
Avec l'évolution des SDK .NET et de MSBuild, il est devenu possible de déclarer cet attribut directement dans le fichier .csproj du projet. Cette méthode offre une approche plus moderne et centralisée que l'ajout direct dans le code source.
Voici comment l'attribut peut être spécifié dans un fichier .csproj :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>MonProjet.Tests</_Parameter1> <!-- Spécifie l'assembly de test qui aura accès aux types internes -->
</AssemblyAttribute>
</ItemGroup>
</Project>
Cette méthode, bien que meilleure que la déclaration dans le code C#, conserve l'inconvénient de la répétition. Chaque projet de la solution nécessiterait d'ajouter ce bloc XML spécifique à son fichier .csproj, avec le nom de l'assembly de test correspondant.
Centralisation avec Directory.Build.props
Pour une gestion véritablement centralisée et scalable, la solution réside dans l'utilisation du fichier Directory.Build.props. Ce fichier, lorsqu'il est placé à la racine d'un dépôt ou d'une solution, est automatiquement importé par tous les fichiers projet SDK-style situés dans le même répertoire ou ses sous-répertoires.
Grâce à Directory.Build.props, nous pouvons définir l'attribut InternalsVisibleTo une seule fois pour tous les projets. L'astuce consiste à utiliser la propriété MSBuild $(AssemblyName), qui représente dynamiquement le nom de l'assembly du projet en cours de construction.
Créez un fichier nommé Directory.Build.props à la racine de votre solution avec le contenu suivant :
<Project>
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>$(AssemblyName).Tests</_Parameter1> <!-- Permet à l'assembly de test correspondant (ex: MonProjet.Tests) d'accéder aux internes -->
</AssemblyAttribute>
</ItemGroup>
</Project>
Avec cette configuration, chaque projet de votre solution, par exemple MaBibliotheque, verra automatiquement son fichier .csproj enrichi de la déclaration permettant à MaBibliotheque.Tests d'accéder à ses types internes. Cette approche élimine la duplication et simplifie considérablement la maintenance des attributs d'assembly pour une architecture de solution complexe.