Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
.NET est une plateforme unifiée unique pour créer n’importe quel type d’application. Il s’efforce de fournir une expérience où vous n’avez pas à raisonner sur les différentes versions de .NET, mais ne tente pas d’extraire complètement le système d’exploitation sous-jacent. Vous pouvez continuer à appeler des API spécifiques à la plateforme, par exemple, P/Invokes et WinRT.
Toutefois, l’utilisation d’API spécifiques à la plateforme sur un composant signifie que le code ne fonctionne plus sur toutes les plateformes. L’analyseur de compatibilité de plateforme et les API complémentaires fournissent des diagnostics pour vous aider à identifier et utiliser des API spécifiques à la plateforme le cas échéant.
Les API complémentaires sont les suivantes :
- SupportedOSPlatformAttribute pour annoter les API comme étant spécifiques à la plateforme et UnsupportedOSPlatformAttribute pour annoter les API comme non prises en charge sur un système d’exploitation particulier. Ces attributs peuvent éventuellement inclure le numéro de version et ont déjà été appliqués à certaines API spécifiques à la plateforme dans les bibliothèques .NET principales.
-
Is<Platform>()etIs<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)méthodes statiques dans la classe System.OperatingSystem pour appeler des API de manière sécurisée spécifiques à la plateforme. Par exemple, OperatingSystem.IsWindows() peut être utilisé pour encadrer un appel à une API spécifique à Windows, et OperatingSystem.IsWindowsVersionAtLeast() peut servir à encadrer un appel API spécifique à Windows versionné. Consultez ces exemples de la façon dont ces méthodes peuvent être utilisées en tant que gardes des références d’API spécifiques à la plateforme.
Conditions préalables
L’analyseur de compatibilité de plateforme est l’un des analyseurs de qualité de code Roslyn. Ces analyseurs sont inclus dans le Kit de développement logiciel (SDK) .NET. L’analyseur de compatibilité de plateforme est activé par défaut uniquement pour les projets qui ciblent net5.0 ou une version ultérieure. Toutefois, vous pouvez l’activer pour les projets qui ciblent d’autres frameworks.
Comment l’analyseur détermine la dépendance de plateforme
Une API non attribuée est considérée comme fonctionnant sur toutes les plateformes de système d’exploitation.
Une API marquée avec
[SupportedOSPlatform("platform")]est considérée comme uniquement portable pour la plateforme spécifiée et toutes les plateformes dont elle est un sous-ensemble.- L’attribut peut être appliqué plusieurs fois pour indiquer la prise en charge de plusieurs plateformes, par exemple
[SupportedOSPlatform("windows"), SupportedOSPlatform("Android29.0")]. - Si la plateforme est un sous-ensemble d’une autre plateforme, l’attribut implique que la plateforme superset est également prise en charge. Par exemple,
[SupportedOSPlatform("iOS")]implique que l'API est prise en charge suriOSet aussi sur sa plateforme superset,MacCatalyst. - L’analyseur génère un avertissement si des API spécifiques à la plateforme sont référencées sans contexte de plateforme approprié :
-
Avertit si le projet ne cible pas la plateforme prise en charge (par exemple, une API spécifique à Windows appelée à partir d’un projet ciblant iOS
<TargetFramework>net5.0-ios14.0</TargetFramework>). -
Avertit si le projet est multiplateforme et appelle des API spécifiques à la plateforme (par exemple, une API spécifique à Windows appelée dans TFM
<TargetFramework>net5.0</TargetFramework>multiplateforme). -
N’avertit pas si l’API spécifique à la plateforme est référencée dans un projet qui cible l’une des plateformes spécifiées (par exemple, pour une API spécifique à Windows appelée à partir d’un projet ciblant des fenêtres
<TargetFramework>net5.0-windows</TargetFramework>et que la génération de fichiers AssemblyInfo.cs est activée pour le projet). -
N’avertit pas si l’appel d’API spécifique à la plateforme est protégé par les méthodes de vérification de plateforme correspondantes (par exemple, un appel d’API spécifique à Windows protégé par
OperatingSystem.IsWindows()). -
N’avertit pas si l’API spécifique à la plateforme est référencée à partir du même contexte spécifique à la plateforme (site d’appel également attribué avec
[SupportedOSPlatform("platform")).
-
Avertit si le projet ne cible pas la plateforme prise en charge (par exemple, une API spécifique à Windows appelée à partir d’un projet ciblant iOS
- L’attribut peut être appliqué plusieurs fois pour indiquer la prise en charge de plusieurs plateformes, par exemple
Une API marquée avec
[UnsupportedOSPlatform("platform")]est considérée comme non prise en charge sur la plateforme spécifiée et toutes les plateformes dont elle est un sous-ensemble, mais prise en charge pour toutes les autres plateformes.- L’attribut peut être appliqué plusieurs fois avec différentes plateformes, par exemple
[UnsupportedOSPlatform("iOS"), UnsupportedOSPlatform("Android29.0")]. - Si la plateforme est un sous-ensemble d’une autre plateforme, l’attribut implique que la plateforme superset n’est pas prise en charge. Par exemple,
[UnsupportedOSPlatform("iOS")]implique que l’API n’est pas prise en charge suriOS, et également sur sa plateforme superset,MacCatalyst. - L’analyseur génère un avertissement uniquement si le
platformest effectivement efficace pour le site d'appel :Avertit si le projet cible une plateforme attribuée comme non prise en charge (par exemple, si l'API est attribuée avec
[UnsupportedOSPlatform("windows")]et que le site d'appel cible<TargetFramework>net5.0-windows</TargetFramework>).Avertit si le projet est multi-ciblé et qu’il
platformest inclus dans le groupe d’éléments MSBuild<SupportedPlatform>par défaut, ou s’ilplatformest inclus manuellement dans leMSBuild<SupportedPlatform>groupe d’éléments :<ItemGroup> <SupportedPlatform Include="platform" /> </ItemGroup>N’avertit pas si vous créez une application qui ne cible pas la plateforme non prise en charge ou qui est multi-ciblée et que la plateforme n’est pas incluse dans le groupe d’éléments MSBuild
<SupportedPlatform>par défaut.
- L’attribut peut être appliqué plusieurs fois avec différentes plateformes, par exemple
Les deux attributs peuvent être instanciés avec ou sans numéros de version dans le cadre du nom de la plateforme. Les numéros de version sont au format
major.minor[.build[.revision]];major.minorest obligatoire et les partiesbuildetrevisionsont facultatives. Par exemple, « Windows6.1 » indique Windows version 6.1, mais « Windows » est interprété comme Windows 0.0.
Pour plus d’informations, consultez des exemples de fonctionnement des attributs et des diagnostics qu’ils provoquent.
Comment l’analyseur reconnaît les plateformes cibles TFM
L’analyseur ne vérifie pas les plateformes cibles de moniker de framework cible (TFM) à partir des propriétés MSBuild, telles que <TargetFramework> ou <TargetFrameworks>. Si le TFM a une plateforme cible, MSBuild injecte un SupportedOSPlatform attribut avec le nom de la plateforme ciblée dans le fichier AssemblyInfo.cs , qui est consommé par l’analyseur. Par exemple, si le TFM est net5.0-windows10.0.19041, MSBuild injecte l’attribut [assembly: System.Runtime.Versioning.SupportedOSPlatform("windows10.0.19041")] dans le fichier AssemblyInfo.cs , et l’assembly entier est considéré comme Windows uniquement. Par conséquent, l’appel d’API « Windows uniquement » avec une version 7.0 ou antérieure ne provoquerait pas d’avertissements dans le projet.
Remarque
Si la génération de fichiers AssemblyInfo.cs est désactivée pour le projet (autrement dit, la <GenerateAssemblyInfo> propriété est définie sur false), l’attribut de niveau SupportedOSPlatform assembly requis ne peut pas être ajouté par MSBuild. Dans ce cas, vous pouvez voir des avertissements pour une utilisation d’API propres à la plateforme, même si vous ciblez cette plateforme. Pour résoudre les avertissements, activez la génération de fichier AssemblyInfo.cs ou ajoutez l’attribut manuellement dans votre projet.
Inclusion de la plateforme
.NET 6 a introduit le concept d’inclusion de plateforme, où une plateforme peut être un sous-ensemble d’une autre plateforme. Une annotation pour la plateforme de sous-ensemble implique la même prise en charge (ou son absence) pour la plateforme de sur-ensemble. Si une méthode de vérification de plateforme dans le OperatingSystem type a un SupportedOSPlatformGuard("supersetPlatform")] attribut, supersetPlatform elle est considérée comme un super-ensemble de la plateforme de système d’exploitation que la méthode recherche.
Par exemple, la OperatingSystem.IsIOS() méthode est attribuée [SupportedOSPlatformGuard("MacCatalyst")]. Par conséquent, les instructions suivantes s’appliquent :
- Les méthodes OperatingSystem.IsIOS() et OperatingSystem.IsIOSVersionAtLeast vérifient non seulement la plateforme
iOS, mais aussi la plateformeMacCatalyst. -
[SupportedOSPlatform("iOS")]implique que l'API est prise en charge suriOSet également sur sa plateforme superset,MacCatalyst. Vous pouvez utiliser l’attribut[UnsupportedOSPlatform("MacCatalyst")]pour exclure cette prise en charge implicite. -
[UnsupportedOSPlatform("iOS")implique que l’API n’est pas prise en charge suriOSetMacCatalyst. Vous pouvez utiliser l’attribut[SupportedOSPlatform("MacCatalyst")]pour exclure ce manque implicite de prise en charge.
Considérez la matrice de couverture suivante, où ✔️ indique que la plateforme est prise en charge et ❌ indique que la plateforme n’est pas prise en charge.
| Plate-forme | SupportedOSPlatform(subset) |
SupportedOSPlatform(superset) |
UnsupportedOSPlatform(subset) |
UnsupportedOSPlatform(superset) |
|---|---|---|---|---|
| Sous-ensemble | ✔️ | ❌ | ✔️ | ❌ |
| Superset | ✔️ | ✔️ | ✔️ | ✔️ |
Conseil / Astuce
Les mêmes règles s'appliquent aux attributs SupportedOSPlatformGuard et UnsupportedOSPlatformGuard.
L’extrait de code suivant montre comment combiner des attributs pour définir le niveau de prise en charge approprié.
// MacCatalyst is a superset of iOS therefore supported on iOS and MacCatalyst
[SupportedOSPlatform("iOS")]
public void ApiOnlySupportedOnIOSAndMacCatalyst() { }
// Does not imply iOS, only supported on MacCatalyst
[SupportedOSPlatform("MacCatalyst")]
public void ApiOnlySupportedOnMacCatalyst() { }
[SupportedOSPlatform("iOS")] // Supported on iOS and MacCatalyst
[UnsupportedOSPlatform("MacCatalyst")] // Removes implied MacCatalyst support
public void ApiOnlySupportedOnIos() { }
// Unsupported on iOS and MacCatalyst
[UnsupportedOSPlatform("iOS")]
public void ApiUnsupportedOnIOSAndMacCatalyst();
// Does not imply iOS, only unsupported on MacCatalyst
[UnsupportedOSPlatform("MacCatalyst")]
public void ApiUnsupportedOnMacCatalyst() { }
[UnsupportedOSPlatform("iOS")] // Unsupported on iOS and MacCatalyst
[SupportedOSPlatform("MacCatalyst")] // Removes implied MacCatalyst unsupportedness
public void ApiUnsupportedOnIos() { }
Scénarios avancés pour les combinaisons d’attributs
Si une combinaison d’attributs
[SupportedOSPlatform]et[UnsupportedOSPlatform]est présente, tous les attributs sont regroupés par identificateur de plateforme du système d’exploitation :Liste des éléments pris en charge uniquement. Si la version la plus basse pour chaque plateforme de système d’exploitation est un attribut
[SupportedOSPlatform], l’API est considérée comme prise en charge uniquement par les plateformes listées et non prise en charge par toutes les autres plateformes. Les attributs facultatifs[UnsupportedOSPlatform]pour chaque plateforme peuvent uniquement avoir une version supérieure de la version minimale prise en charge, ce qui indique que l’API est supprimée à partir de la version spécifiée.// API is only supported on Windows from version 6.2 to 10.0.19041.0 and all versions of Linux // The API is considered not supported for all other platforms. [SupportedOSPlatform("windows6.2")] [UnsupportedOSPlatform("windows10.0.19041.0")] [SupportedOSPlatform("linux")] public void ApiSupportedFromWindows80SupportFromCertainVersion();Liste des éléments non pris en charge uniquement. Si la version la plus basse pour chaque plateforme de système d’exploitation est un attribut
[UnsupportedOSPlatform], l’API est considérée comme n’étant pas prise en charge uniquement par les plateformes listées, et prise en charge par toutes les autres plateformes. La liste peut avoir[SupportedOSPlatform]un attribut avec la même plateforme, mais une version supérieure, ce qui indique que l’API est prise en charge à partir de cette version.// The API is unsupported on all Linux versions was unsupported on Windows until version 10.0.19041.0. // The API is considered supported everywhere else without constraints. [UnsupportedOSPlatform("windows")] [SupportedOSPlatform("windows10.0.19041.0")] [UnsupportedOSPlatform("linux")] public void ApiSupportedFromWindows8UnsupportedFromWindows10();Liste d’incohérence. Si la version la plus basse pour certaines plateformes est
[SupportedOSPlatform], tandis qu’elle est[UnsupportedOSPlatform]pour d'autres plateformes, cela est considéré comme incohérent, ce qui n’est pas pris en charge par l’analyseur. Si l’incohérence se produit, l’analyseur ignore les[UnsupportedOSPlatform]plateformes.- Si les versions les plus basses des attributs
[SupportedOSPlatform]et[UnsupportedOSPlatform]sont égales, l'analyseur considère la plateforme comme faisant partie de la liste de prise en charge uniquement.
- Si les versions les plus basses des attributs
Les attributs de plateforme peuvent être appliqués aux types, aux membres (méthodes, champs, propriétés et événements) et aux assemblys avec différents noms ou versions de plateforme.
- Les attributs appliqués au niveau
targetsupérieur affectent tous ses membres et types. - Les attributs au niveau enfant s’appliquent uniquement s’ils respectent la règle selon laquelle « les annotations enfants peuvent limiter la prise en charge des plateformes, mais elles ne peuvent pas l’étendre ».
- Lorsque le parent a une liste de type Supporté uniquement, les attributs des membres enfants ne peuvent pas ajouter de nouveau support de plateforme, car cela équivaudrait à étendre le support du parent. La prise en charge d'une nouvelle plateforme ne peut être ajoutée qu'au parent lui-même. Mais l’enfant peut avoir l’attribut
Supportedpour la même plateforme avec les versions ultérieures, car cela limite la prise en charge. En outre, l’enfant peut avoir l’attributUnsupportedavec la même plateforme, ce qui limite également le soutien des parents. - Lorsque le parent a une liste d'éléments uniquement non pris en charge, alors les attributs des membres enfants peuvent ajouter la prise en charge d'une nouvelle plateforme, car cela restreint la prise en charge des parents. Mais il ne peut pas avoir l’attribut
Supportedpour la même plateforme que le parent, car cela étend la prise en charge du parent. La prise en charge de la même plateforme ne peut être implémentée qu’au parent où l’attribut d’origineUnsupporteda été appliqué.
- Lorsque le parent a une liste de type Supporté uniquement, les attributs des membres enfants ne peuvent pas ajouter de nouveau support de plateforme, car cela équivaudrait à étendre le support du parent. La prise en charge d'une nouvelle plateforme ne peut être ajoutée qu'au parent lui-même. Mais l’enfant peut avoir l’attribut
- Si
[SupportedOSPlatform("platformVersion")]est utilisé plusieurs fois pour une API ayant le même nomplatform, l’analyseur considère uniquement celui qui a la version minimale. - Si
[UnsupportedOSPlatform("platformVersion")]est appliqué plus de deux fois pour une API portant le mêmeplatformnom, l'analyseur considère uniquement les deux versions les plus anciennes.
Remarque
Une API qui a été prise en charge initialement mais non prise en charge (supprimée) dans une version ultérieure n’est pas censée être prise en charge dans une version encore plus récente.
- Les attributs appliqués au niveau
Exemples de fonctionnement des attributs et des diagnostics qu’ils produisent
// An API supported only on Windows all versions.
[SupportedOSPlatform("Windows")]
public void WindowsOnlyApi() { }
// an API supported on Windows and Linux.
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
public void SupportedOnWindowsAndLinuxOnly() { }
// an API only supported on Windows 6.2 and later, not supported for all other.
// an API is removed/unsupported from version 10.0.19041.0.
[SupportedOSPlatform("windows6.2")]
[UnsupportedOSPlatform("windows10.0.19041.0")]
public void ApiSupportedFromWindows8UnsupportedFromWindows10() { }
// an Assembly supported on Windows, the API added from version 10.0.19041.0.
[assembly: SupportedOSPlatform("Windows")]
[SupportedOSPlatform("windows10.0.19041.0")]
public void AssemblySupportedOnWindowsApiSupportedFromWindows10() { }
public void Caller()
{
WindowsOnlyApi(); // warns: This call site is reachable on all platforms. 'WindowsOnlyApi()' is only supported on: 'windows'
// This call site is reachable on all platforms. 'SupportedOnWindowsAndLinuxOnly()' is only supported on: 'Windows', 'Linux'
SupportedOnWindowsAndLinuxOnly();
// This call site is reachable on all platforms. 'ApiSupportedFromWindows8UnsupportedFromWindows10()' is only supported on: 'windows' from version 6.2 to 10.0.19041.0
ApiSupportedFromWindows8UnsupportedFromWindows10();
// for same platform analyzer only warn for the latest version.
// This call site is reachable on all platforms. 'AssemblySupportedOnWindowsApiSupportedFromWindows10()' is only supported on: 'windows' 10.0.19041.0 and later
AssemblySupportedOnWindowsApiSupportedFromWindows10();
}
// an API not supported on android but supported on all other.
[UnsupportedOSPlatform("android")]
public void DoesNotWorkOnAndroid() { }
// an API was unsupported on Windows until version 6.2.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows6.2")]
public void StartedWindowsSupportFromVersion8() { }
// an API was unsupported on Windows until version 6.2.
// Then the API is removed (unsupported) from version 10.0.19041.0.
// The API is considered supported everywhere else without constraints.
[UnsupportedOSPlatform("windows")]
[SupportedOSPlatform("windows6.2")]
[UnsupportedOSPlatform("windows10.0.19041.0")]
public void StartedWindowsSupportFrom8UnsupportedFrom10() { }
public void Caller2()
{
DoesNotWorkOnAndroid(); // This call site is reachable on all platforms.'DoesNotWorkOnAndroid()' is unsupported on: 'android'
// This call site is reachable on all platforms. 'StartedWindowsSupportFromVersion8()' is unsupported on: 'windows' 6.2 and before.
StartedWindowsSupportFromVersion8();
// This call site is reachable on all platforms. 'StartedWindowsSupportFrom8UnsupportedFrom10()' is supported on: 'windows' from version 6.2 to 10.0.19041.0
StartedWindowsSupportFrom8UnsupportedFrom10();
}
Gérer les avertissements signalés
La méthode recommandée pour traiter ces diagnostics consiste à vous assurer que vous appelez uniquement des API spécifiques à la plateforme lors de l’exécution sur une plateforme appropriée. Voici les options que vous pouvez utiliser pour traiter les avertissements ; choisissez le choix qui convient le mieux à votre situation :
Surveillez l’appel. Pour ce faire, appelez le code de manière conditionnelle au moment de l’exécution. Vérifiez si vous exécutez sur la plateforme souhaitée
Platformen utilisant l'une des méthodes de vérification de plateforme, par exempleOperatingSystem.Is<Platform>()ouOperatingSystem.Is<Platform>VersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0). Exemple de.Marquez le site d’appel comme propre à la plateforme. Vous pouvez également choisir de marquer vos propres API comme propres à la plateforme, ce qui vous permet de transférer efficacement les exigences à vos appelants. Marquez une méthode ou un type contenant, ou l'assembly entier avec les mêmes attributs que l'appel référencé dépendant de la plateforme. Exemples.
Affirmez le site d’appel avec vérification de la plateforme. Si vous ne souhaitez pas la surcharge d’une instruction supplémentaire
ifau moment de l’exécution, utilisez Debug.Assert(Boolean). Exemple de.Supprimez le code. En règle générale, ce n’est pas ce que vous voulez, car cela signifie que vous perdez la fidélité lorsque votre code est utilisé par les utilisateurs Windows. Pour les cas où une alternative multiplateforme existe, vous feriez probablement mieux d'utiliser celle-ci plutôt que les API spécifiques à la plateforme.
Supprimez l’avertissement. Vous pouvez également simplement supprimer l’avertissement, soit via une entrée EditorConfig , soit
#pragma warning disable CA1416. Toutefois, cette option doit être un dernier recours lors de l’utilisation d’API spécifiques à la plateforme.Conseil / Astuce
Lors de la désactivation des avertissements à l’aide des directives du précompilateur
#pragma, les identificateurs que vous ciblez sont sensibles à la casse. Par exemple,ca1416ne désactive pas réellement l’avertissement CA1416.
API spécifiques à la plateforme Guard avec des méthodes de protection
Le nom de la plateforme de la méthode guard doit correspondre au nom de la plateforme d’API dépendante de la plateforme appelante. Si la chaîne de plateforme de l’API appelante inclut la version :
Pour l’attribut
[SupportedOSPlatform("platformVersion")], la plateforme de la méthode guardversiondoit être supérieure ou égale à celle de la plateforme appelanteVersion.Pour l’attribut
[UnsupportedOSPlatform("platformVersion")], la plateformeversionde la méthode guard doit être inférieure ou égale à celle deVersionla plateforme appelante.public void CallingSupportedOnlyApis() // Allow list calls { if (OperatingSystem.IsWindows()) { WindowsOnlyApi(); // will not warn } if (OperatingSystem.IsLinux()) { SupportedOnWindowsAndLinuxOnly(); // will not warn, within one of the supported context } // Can use &&, || logical operators to guard combined attributes if (OperatingSystem.IsWindowsVersionAtLeast(6, 2) && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041))) { ApiSupportedFromWindows8UnsupportedFromWindows10(); } if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041, 0)) { AssemblySupportedOnWindowsApiSupportedFromWindows10(); // Only need to check latest supported version } } public void CallingUnsupportedApis() { if (!OperatingSystem.IsAndroid()) { DoesNotWorkOnAndroid(); // will not warn } if (!OperatingSystem.IsWindows() || OperatingSystem.IsWindowsVersionAtLeast(6, 2)) { StartedWindowsSupportFromVersion8(); // will not warn } if (!OperatingSystem.IsWindows() || // supported all other platforms (OperatingSystem.IsWindowsVersionAtLeast(6, 2) && !OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041))) { StartedWindowsSupportFrom8UnsupportedFrom10(); // will not warn } }Si vous devez protéger le code qui cible
netstandardounetcoreappoù de nouvelles OperatingSystem API ne sont pas disponibles, l’API RuntimeInformation.IsOSPlatform peut être utilisée et sera respectée par l’analyseur. Mais ce n’est pas aussi optimisé que les nouvelles API ajoutées dans OperatingSystem. Si la plateforme n’est pas prise en charge dans le OSPlatform struct, vous pouvez appeler OSPlatform.Create(String) et transmettre le nom de la plateforme, que l’analyseur respecte également.public void CallingSupportedOnlyApis() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { SupportedOnWindowsAndLinuxOnly(); // will not warn } if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("browser"))) { ApiOnlySupportedOnBrowser(); // call of browser specific API } }
Annoter les API avec des attributs platform guard et les utiliser comme garde personnalisé
Comme indiqué précédemment, l’analyseur reconnaît les méthodes statiques platform-guard dans le OperatingSystem type, telles que OperatingSystem.IsWindows, et également RuntimeInformation.IsOSPlatform. Toutefois, vous pouvez mettre en cache le résultat de la protection dans un champ et le réutiliser, ou utiliser des méthodes de protection personnalisées pour vérifier une plateforme. L'analyseur doit reconnaître ces API en tant que gardes personnalisés et ne doit pas signaler d'avertissements pour les API protégées par ceux-ci. Les attributs guard ont été introduits dans .NET 6 pour prendre en charge ce scénario :
-
SupportedOSPlatformGuardAttributeannote les API qui peuvent être utilisées comme protection pour les API annotées avec SupportedOSPlatformAttribute. -
UnsupportedOSPlatformGuardAttributeannote les API qui peuvent être utilisées comme protection pour les API annotées avec UnsupportedOSPlatformAttribute.
Ces attributs peuvent éventuellement inclure un numéro de version. Ils peuvent être appliqués plusieurs fois pour protéger plusieurs plateformes et peuvent être utilisés pour annoter un champ, une propriété ou une méthode.
class Test
{
[UnsupportedOSPlatformGuard("browser")] // The platform guard attribute
#if TARGET_BROWSER
internal bool IsSupported => false;
#else
internal bool IsSupported => true;
#endif
[UnsupportedOSPlatform("browser")]
void ApiNotSupportedOnBrowser() { }
void M1()
{
ApiNotSupportedOnBrowser(); // Warns: This call site is reachable on all platforms.'ApiNotSupportedOnBrowser()' is unsupported on: 'browser'
if (IsSupported)
{
ApiNotSupportedOnBrowser(); // Not warn
}
}
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("Linux")]
void ApiOnlyWorkOnWindowsLinux() { }
[SupportedOSPlatformGuard("Linux")]
[SupportedOSPlatformGuard("Windows")]
private readonly bool _isWindowOrLinux = OperatingSystem.IsLinux() || OperatingSystem.IsWindows();
void M2()
{
ApiOnlyWorkOnWindowsLinux(); // This call site is reachable on all platforms.'ApiOnlyWorkOnWindowsLinux()' is only supported on: 'Linux', 'Windows'.
if (_isWindowOrLinux)
{
ApiOnlyWorkOnWindowsLinux(); // Not warn
}
}
}
Marquer le site d’appel comme propre à la plateforme
Les noms de plateforme doivent correspondre à l’API dépendante de la plateforme appelante. Si la chaîne de plateforme inclut une version :
Pour l’attribut
[SupportedOSPlatform("platformVersion")], la plateformeversionde site d’appel doit être supérieure ou égale à celle de la plateforme appelanteVersionPour l’attribut
[UnsupportedOSPlatform("platformVersion")], la plateformeversionde site d’appel doit être inférieure ou égale à celle de la plateforme appelanteVersion// an API supported only on Windows. [SupportedOSPlatform("windows")] public void WindowsOnlyApi() { } // an API supported on Windows and Linux. [SupportedOSPlatform("Windows")] [SupportedOSPlatform("Linux")] public void SupportedOnWindowsAndLinuxOnly() { } // an API only supported on Windows 6.2 and later, not supported for all other. // an API is removed/unsupported from version 10.0.19041.0. [SupportedOSPlatform("windows6.2")] [UnsupportedOSPlatform("windows10.0.19041.0")] public void ApiSupportedFromWindows8UnsupportedFromWindows10() { } // an Assembly supported on Windows, the API added from version 10.0.19041.0. [assembly: SupportedOSPlatform("Windows")] [SupportedOSPlatform("windows10.0.19041.0")] public void AssemblySupportedOnWindowsApiSupportedFromWindows10() { } [SupportedOSPlatform("windows6.2")] // call site attributed Windows 6.2 or above. public void Caller() { WindowsOnlyApi(); // will not warn as call site is for Windows. // will not warn as call site is for Windows all versions. SupportedOnWindowsAndLinuxOnly(); // will not warn for the [SupportedOSPlatform("windows6.2")] attribute, but warns for [UnsupportedOSPlatform("windows10.0.19041.0")] // This call site is reachable on: 'windows' 6.2 and later. 'ApiSupportedFromWindows8UnsupportedFromWindows10()' is unsupported on: 'windows' 10.0.19041.0 and later. ApiSupportedFromWindows8UnsupportedFromWindows10(); // The call site version is lower than the calling version, so warns: // This call site is reachable on: 'windows' 6.2 and later. 'AssemblySupportedOnWindowsApiSupportedFromWindows10()' is only supported on: 'windows' 10.0.19041.0 and later AssemblySupportedOnWindowsApiSupportedFromWindows10(); } [SupportedOSPlatform("windows10.0.22000")] // call site attributed with windows 10.0.22000 or above. public void Caller2() { // This call site is reachable on: 'windows' 10.0.22000 and later. 'ApiSupportedFromWindows8UnsupportedFromWindows10()' is unsupported on: 'windows' 10.0.19041.0 and later. ApiSupportedFromWindows8UnsupportedFromWindows10(); // will not warn as call site version higher than calling API. AssemblySupportedOnWindowsApiSupportedFromWindows10(); } [SupportedOSPlatform("windows6.2")] [UnsupportedOSPlatform("windows10.0.19041.0")] // call site supports Windows from version 6.2 to 10.0.19041.0. public void Caller3() { // will not warn as caller has exact same attributes. ApiSupportedFromWindows8UnsupportedFromWindows10(); // The call site reachable for the version not supported in the calling API, therefore warns: // This call site is reachable on: 'windows' from version 6.2 to 10.0.19041.0. 'AssemblySupportedOnWindowsApiSupportedFromWindows10()' is only supported on: 'windows' 10.0.19041.0 and later. AssemblySupportedOnWindowsApiSupportedFromWindows10(); } // an API not supported on Android but supported on all other. [UnsupportedOSPlatform("android")] public void DoesNotWorkOnAndroid() { } // an API was unsupported on Windows until version 6.2. // The API is considered supported everywhere else without constraints. [UnsupportedOSPlatform("windows")] [SupportedOSPlatform("windows6.2")] public void StartedWindowsSupportFromVersion8() { } // an API was unsupported on Windows until version 6.2. // Then the API is removed (unsupported) from version 10.0.19041.0. // The API is considered supported everywhere else without constraints. [UnsupportedOSPlatform("windows")] [SupportedOSPlatform("windows6.2")] [UnsupportedOSPlatform("windows10.0.19041.0")] public void StartedWindowsSupportFrom8UnsupportedFrom10() { } [UnsupportedOSPlatform("windows")] // Caller no support Windows for any version. public void Caller4() { // This call site is reachable on all platforms.'DoesNotWorkOnAndroid()' is unsupported on: 'android' DoesNotWorkOnAndroid(); // will not warns as the call site not support Windows at all, but supports all other. StartedWindowsSupportFromVersion8(); // same, will not warns as the call site not support Windows at all, but supports all other. StartedWindowsSupportFrom8UnsupportedFrom10(); } [UnsupportedOSPlatform("windows")] [UnsupportedOSPlatform("android")] // Caller not support Windows and Android for any version. public void Caller4() { DoesNotWorkOnAndroid(); // will not warn as call site not supports Android. // will not warns as the call site not support Windows at all, but supports all other. StartedWindowsSupportFromVersion8(); // same, will not warns as the call site not support Windows at all, but supports all other. StartedWindowsSupportFrom8UnsupportedFrom10(); }
Affirmer le site d’appel avec vérification de la plateforme
Toutes les vérifications conditionnelles utilisées dans les exemples de garde de plateforme peuvent également servir de condition pour Debug.Assert(Boolean).
// An API supported only on Linux.
[SupportedOSPlatform("linux")]
public void LinuxOnlyApi() { }
public void Caller()
{
Debug.Assert(OperatingSystem.IsLinux());
LinuxOnlyApi(); // will not warn
}