Partager via


Ciblage multiplateforme

L’infrastructure .NET moderne prend en charge plusieurs systèmes d’exploitation et appareils. Il est important que les bibliothèques .NET open source prennent en charge autant de développeurs que possible, que ce soit pour développer un site Web ASP.NET hébergé dans Azure ou un jeu .NET dans Unity.

Cibles .NET et .NET Standard

Les cibles .NET et .NET Standard constituent la meilleure façon d’ajouter une prise en charge multiplateforme à une bibliothèque .NET.

  • .NET Standard est une spécification des API .NET disponibles sur toutes les implémentations de .NET. Le ciblage .NET Standard vous permet de générer des bibliothèques contraintes d’utiliser des API dans une version donnée de .NET Standard, ce qui signifie qu’il est utilisable par toutes les plateformes qui implémentent cette version de .NET Standard.
  • .NET 6-8 sont des implémentations de .NET. Chaque version est un produit unique avec un ensemble uniforme de fonctionnalités et d’API utilisables pour des applications de bureau Windows et des applications console multiplateformes, des services cloud et des sites web.

Pour plus d’informations sur les différences entre .NET et .NET Standard, consultez .NET 5 et .NET Standard.

.NET Standard

Si votre projet cible .NET ou .NET Standard et compile avec succès, cela ne garantit pas que la bibliothèque fonctionnera avec succès sur toutes les plateformes :

  • des API propres à une plateforme échoueront sur d’autres plateformes. Par exemple, Microsoft.Win32.Registry réussiront sur Windows mais lèveront une exception PlatformNotSupportedException s’ils sont utilisés sur n’importe quel autre système d’exploitation.
  • Les API peuvent se comporter différemment. Par exemple, les API de réflexion ont des caractéristiques de performances différentes lorsqu’une application utilise la compilation AOT (Ahead Of Time) sur iOS ou UWP.

Conseil

L’équipe .NET propose un analyseur de compatibilité de plateforme pour vous aider à détecter les éventuels problèmes.

✔️ À FAIRE : Commencer par inclure une cible netstandard2.0.

La plupart des bibliothèques à usage général n’ont pas besoin d’API en dehors de .NET Standard 2.0. .NET Standard 2.0 est pris en charge par toutes les plateformes modernes et constitue la méthode recommandée pour prendre en charge plusieurs plateformes avec une cible. Si vous n’avez pas besoin de prendre en charge .NET Framework, vous pouvez également viser .NET Standard 2.1.

✔️ INCLUEZ une cible net6.0 ou version ultérieure si vous avez besoin de nouvelles API introduites dans un .NET moderne.

Les applications .NET 6 et version ultérieure peuvent utiliser une cible netstandard2.0, si bien que net6.0 n’est pas nécessaire. Vous devez cibler explicitement net6.0, net7.0, ou net8.0 lorsque vous souhaitez utiliser des API .NET plus récentes.

❌ ÉVITEZ d’inclure une cible netstandard1.x.

.NET Standard 1.x est distribué sous la forme d’un ensemble précis de packages NuGet, qui crée un grand graphique des dépendances de package et amène les développeurs lors du téléchargement d’un grand nombre de packages lors de la génération. Les implémentations .NET modernes prennent en charge .NET Standard 2.0. Vous devez uniquement cibler .NET Standard 1.x si vous avez besoin de cibler une plateforme plus ancienne.

✔️ À FAIRE  : Inclure une cible netstandard2.0 si vous avez besoin d’une cible netstandard1.x.

Toutes les plateformes prenant en charge .NET Standard 2.0 utiliseront la cible netstandard2.0 et bénéficieront d’un graphique de packages plus petit, tandis que les anciennes plateformes continueront de fonctionner et utiliseront la cible netstandard1.x.

❌ N’INCLUEZ PAS une cible .NET Standard si la bibliothèque s’appuie sur un modèle d’application propre à la plateforme.

Par exemple, une bibliothèque de boîte à outils de contrôle UWP dépend d’un modèle d’application uniquement disponible sur UWP. Les API spécifiques à un modèle d’application ne sont pas disponibles dans .NET Standard.

Multi-ciblage

Parfois, vous avez besoin accéder à des API spécifiques à une infrastructure à partir de vos bibliothèques. La meilleure façon d’appeler des API spécifiques à une infrastructure consiste à utiliser le multi-ciblage, qui génère votre projet pour un grand nombre d’infrastructures .NET cible plutôt que pour une seule.

Pour éviter à vos consommateurs d’avoir à créer pour chaque infrastructure, vous devez vous efforcer d’avoir une sortie Standard .NET ainsi qu’une ou plusieurs sorties spécifiques à l’infrastructure. Avec votre multi-ciblage, tous les assemblys sont empaquetés dans un même package NuGet. Les consommateurs peuvent ensuite référencer le même package, et NuGet choisit l’implémentation appropriée. Votre bibliothèque .NET Standard sert de bibliothèque de secours utilisée partout, sauf si votre package NuGet offre une implémentation spécifique à une infrastructure. Le multi-ciblage permet d’utiliser la compilation conditionnelle dans votre code et d’appeler des API spécifiques à une infrastructure.

NuGet package with multiple assemblies

✔️ À ENVISAGER : cibler des implémentations .NET en plus de .NET Standard.

Le ciblage d’implémentations .NET vous permet d’appeler des API spécifiques à la plateforme qui sont trouvent en dehors de .NET Standard.

Ne supprimez pas la prise en charge de .NET Standard lorsque vous effectuez cette opération. Au lieu de cela, levez une exception à partir de l’implémentation et offrez la fonctionnalité API. De cette façon, votre bibliothèque peut être utilisée partout et prend en charge le runtime des fonctionnalités.

public static class GpsLocation
{
    // This project uses multi-targeting to expose device-specific APIs to .NET Standard.
    public static async Task<(double latitude, double longitude)> GetCoordinatesAsync()
    {
#if NET462
        return CallDotNetFrameworkApi();
#elif WINDOWS_UWP
        return CallUwpApi();
#else
        throw new PlatformNotSupportedException();
#endif
    }

    // Allows callers to check without having to catch PlatformNotSupportedException
    // or replicating the OS check.
    public static bool IsSupported
    {
        get
        {
#if NET462 || WINDOWS_UWP
            return true;
#else
            return false;
#endif
        }
    }
}

✔️ Envisagez d’utiliser le multi-ciblage même si votre code source est le même pour toutes les cibles, lorsque votre projet a des dépendances pour bibliothèque/package.

Les packages dépendants de votre projet, directs ou en aval, peuvent utiliser les mêmes API de code tout en étant enveloppées dans différentes versions de l’assembly dépendant par framework cible. L’ajout de cibles spécifiques garantit que vos consommateurs n’ont pas besoin d’ajouter ni de mettre à jour leurs redirections de liaison d’assembly.

❌ Évitez le multi-ciblage, ainsi que le ciblage de .NET Standard si votre code source est identique pour toutes les cibles et que votre projet n’a pas de dépendances de bibliothèque ni de package.

L’assembly .NET Standard sera automatiquement utilisé par NuGet. Le ciblage d’implémentations .NET individuelles augmente la taille *.nupkg sans apporter d’avantage.

✔️ À ENVISAGER : Ajouter une cible pour net462 lorsque que vous proposez une cible netstandard2.0.

L’utilisation de .NET Standard 2.0 dans .NET Framework entraîne certains problèmes qui ont été résolus dans .NET Framework 4.7.2. Vous pouvez améliorer l’expérience des développeurs qui utilisent toujours .NET Framework 4.6.2 – 4.7.1 en leur offrant un fichier binaire conçu pour .NET Framework 4.6.2.

✔️ À FAIRE : Distribuer votre bibliothèque à l’aide d’un package NuGet.

NuGet sélectionnera la meilleure cible pour les développeurs et leur évitera d’avoir à choisir l’implémentation appropriée.

✔️ À FAIRE : Utiliser la propriété TargetFrameworks d’un fichier projet lors du multi-ciblage.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <!-- This project will output netstandard2.0 and net462 assemblies -->
    <TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
  </PropertyGroup>
</Project>

✔️ À ENVISAGER : Utiliser MSBuild.Sdk.Extras lors du multi-ciblage pour UWP et Xamarin car cela simplifie considérablement votre fichier projet.

❌ ÉVITEZ de modifier le nom de l’assembly ou d’utiliser des noms d’assembly différents pour chaque moniker de framework cible compilé par votre bibliothèque. En raison des dépendances entre les bibliothèques, le ciblage multiple avec différents noms d’assembly par le moniker de framework cible peut interrompre les consommateurs de packages. Un assembly doit avoir le même nom sur tous les monikers de framework cible.

Anciennes cibles

.NET permet de cibler les versions de .NET Framework qui ne sont plus prises en charge, ainsi que les plates-formes qui ne sont plus utilisées couramment. Bien qu'il soit utile de faire fonctionner votre bibliothèque sur autant de cibles que possible, le fait de devoir contourner des API manquantes peut entraîner d’importants frais généraux. Compte tenu de leur portée et de leurs limites, certains cadres ne méritent plus d’être ciblés.

❌ N’INCLUEZ PAS une cible Portable Class Library (PCL). Par exemple : portable-net45+win8+wpa81+wp8.

.NET standard est la méthode moderne de prendre en charge les bibliothèques .NET multiplateformes et remplace les PCL.

❌ N’INCLUEZ PAS des cibles pour les plateformes .NET qui ne sont plus prises en charge. Par exemple, SL4, WP.