Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

.NET 5.0, C#9, IoT 2020 … ca bouge beaucoup !

Il n’y a pas vraiment de surprise à proprement parlé puisque ces évolutions sont annoncées depuis un moment, mais les voir arriver, pouvoir les télécharger et les tester cela fait une différence de taille ! D’autant que nous parlons ici d’avancées majeures bouleversant un peu le monde .NET et C# autant que celui des IoT

Une annonce énorme !

L’annonce est en effet de taille, pas seulement de façon imagée par l’impact des nouveautés, mais même par la taille du post sur Blog.Net de Microsoft, un véritable roman !

Il faut dire que le nombre des annonces est impressionnant autant que leurs implications.

C’est pourquoi j’ai décidé aujourd’hui de vous livrer une traduction de cette annonce in extenso, je reviendrai bien évidemment sur de nombreux points, voire tous, dans de prochains billets. Le temps de télécharger et de tester moi aussi. Tous les billets Dot.Blog se basent sur mon expérience et mon expertise, et comment être honnête si je publie une analyse sur des produits que je n’ai pas eu le temps d’utiliser ? C’est pourquoi je ne le ferai pas. Mais les annonces sont si importantes que je ne peux pas non plus les passer sous silence. D’où le choix de traduire le texte de l’annonce originale. Je n’ai pas encore testé tout cela, mais vous ne serez pas privé d’une information essentielle.

Attention : étant donnée la taille du texte et le mélange image / texte / extraits de code, j’ai utilisé Google Traduction pour ne pas y passer la journée. Mais rien que pour rendre l’ensemble lisible cela m’a pris plus d’une heure et demi et c’est loin d’être parfait. Mais je pense avoir un bon compromis entre traduction parfaite et rapidité de mise en ligne de ces informations cruciales. Merci de votre indulgence par avance ! Je reviendrai de toute façon plus en détail sous le format habituel dans les semaines et mois à venir tant il y a de choses à expérimenter !

Si vous préférez lire l’intégralité de ce texte dans sa version originale en langue cowboy cliquez ici !

L’annonce

Voici l’annonce du 10 novembre dans son intégralité, avec tous ses liens. Comme vous allez le voir tout est important, tout est essentiel, tout aura un impact sur nos productions, impossible donc de trier le bon grain de l’ivraie pour vous proposer un résumé car il n’y a rien à jeter ici ! Le post ici traduit émane de Richard Lander, Program Manager dans l’équipe .NET, donc quelqu’un de très bien placé pour parler de tout cela. Publié le 10/11/2020 donc, voici le texte :

Annonce de .NET 5.0

Avatar

Richard

Nous sommes ravis de publier .NET 5.0 aujourd'hui et que vous commenciez à l'utiliser. Il s'agit d'une version majeure - y compris C # 9 et F # 5 - avec un large éventail de nouvelles fonctionnalités et d'améliorations convaincantes. Il est déjà utilisé activement par les équipes de Microsoft et d'autres entreprises, en production et pour les tests de performances. Ces équipes nous montrent d'excellents résultats qui démontrent des gains de performances et / ou des opportunités de réduire les coûts d'hébergement de leurs applications Web. Nous exploitons notre propre site Web sur la version 5.0 depuis l'aperçu 1. D'après ce que nous avons vu et entendu jusqu'à présent, .NET 5.0 offre une valeur significative sans trop d'efforts de mise à niveau. C'est un excellent choix pour votre prochaine application et une mise à niveau simple à partir des versions antérieures de .NET Core. Nous espérons que vous apprécierez de l'utiliser sur votre ordinateur de bureau, votre ordinateur portable et vos instances cloud.

ASP.NET Core , EF Core , C # 9 et F # 5 sont également publiés aujourd'hui. .NET Conf 2020 - notre conférence gratuite et virtuelle - se tient aujourd'hui afin que vous puissiez en savoir plus sur toutes les nouvelles versions.

Vous pouvez télécharger .NET 5.0 , pour Windows, macOS et Linux, pour x86, x64, Arm32, Arm64.

Pour les utilisateurs de Visual Studio, vous avez besoin de Visual Studio 16.8 ou version ultérieure pour utiliser .NET 5.0 sur Windows et la dernière version de Visual Studio pour Mac) sur macOS. L' extension C # pour Visual Studio Code prend déjà en charge .NET 5.0 et C # 9.

.NET 5.0 est la première version de notre voyage d'unification .NET. Nous avons créé .NET 5.0 pour permettre à un groupe beaucoup plus important de développeurs de migrer leur code et leurs applications .NET Framework vers .NET 5.0. Nous avons également effectué une grande partie des premiers travaux de la version 5.0 afin que les développeurs Xamarin puissent utiliser la plate-forme unifiée .NET lorsque nous publierons .NET 6.0. Il y en a plus sur l'unification .NET, plus loin dans l'article.

Le moment est venu de souligner l'incroyable collaboration avec tous ceux qui contribuent au projet .NET. Cette version marque la cinquième version majeure de .NET en tant que projet open source. Il y a maintenant un grand mélange d'individus et de petites et grandes entreprises (y compris les sponsors de la Fondation .NET ) qui travaillent ensemble en tant que grande communauté sur divers aspects de .NET dans l' organisation dotnet sur GitHub . Les améliorations apportées à .NET 5.0 sont le résultat de nombreuses personnes, de leurs efforts, de leurs idées intelligentes, de leur attention et de leur amour pour la plate-forme, tout cela au-delà de la gestion du projet par Microsoft. De la part de l'équipe principale travaillant quotidiennement sur .NET, nous remercions tous ceux qui ont contribué à .NET 5.0 (et aux versions précédentes)!

Nous avons introduit .NET 5.0 en mai 2019 et même défini la date de sortie de novembre 2020 à ce moment-là. D'après ce post: «nous expédierons .NET Core 3.0 en septembre, .NET 5 en novembre 2020, puis nous avons l'intention de livrer une version majeure de .NET une fois par an, chaque novembre». On pourrait penser que «novembre 2020» était un chèque en blanc compte tenu de tous les défis de cette année, cependant, .NET 5.0 a été publié à temps. Merci à tous les membres de l'équipe qui ont rendu cela possible! Je sais que cela n'a pas été facile. Pour l'avenir, vous devriez vous attendre à .NET 6.0 en novembre 2021. Nous avons l'intention de publier de nouvelles versions de .NET chaque novembre.

Le reste du blog est dédié à la mise en évidence et au détail de la plupart des améliorations de .NET 5.0. Il y a aussi une mise à jour sur notre vision d'unification .NET.

Points forts de .NET 5.0

Il existe de nombreuses améliorations importantes dans .NET 5.0 :

J'ai écrit de nombreux exemples pour les articles de prévisualisation .NET 5.0. Vous voudrez peut-être jeter un œil aux exemples .NET 5.0 pour en savoir plus sur les nouvelles fonctionnalités de C # 9 et des bibliothèques.

Plateforme et support Microsoft

.NET 5.0 a une matrice de prise en charge de plate-forme presque identique à .NET Core 3.1 , pour Windows, macOS et Linux. Si vous utilisez .NET Core 3.1 sur un système d'exploitation pris en charge, vous devriez pouvoir adopter .NET 5.0 sur cette même version du système d'exploitation pour la plupart. L'ajout le plus important pour .NET 5.0 est Windows Arm64.

.NET 5.0 est une version actuelle . Cela signifie qu'il sera pris en charge pendant trois mois après la sortie de .NET 6.0. Par conséquent, nous prévoyons de prendre en charge .NET 5.0 jusqu'à la mi-février 2022. .NET 6.0 sera une version LTS et sera pris en charge pendant trois ans, tout comme .NET Core 3.1.

Vision d’une plateforme unifiée

L'année dernière, nous avons partagé une vision d'une pile et d'un écosystème .NET unifiés . L'intérêt pour vous est que vous pourrez utiliser un seul ensemble d'API, de langages et d'outils pour cibler un large éventail de types d'applications, y compris les mobiles, le cloud, les ordinateurs de bureau et l'IoT. Vous réalisez peut-être que vous pouvez déjà cibler un large éventail de plates-formes avec .NET aujourd'hui, cependant, les outils et les API ne sont pas toujours les mêmes sur le Web et le mobile, par exemple, ou publiés en même temps.

Dans le cadre de .NET 5.0 et 6.0, nous unissons .NET en une seule expérience produit, tout en vous permettant de sélectionner uniquement les parties de la plate-forme .NET que vous souhaitez utiliser. Si vous souhaitez cibler Mobile et non WebAssembly, vous n'avez pas besoin de télécharger les outils WebAssembly, et vice versa. Idem avec ASP.NET Core et WPF. Vous aurez également un moyen beaucoup plus simple d'acquérir tous les outils .NET et les packs de compilation et d'exécution dont vous avez besoin à partir de la ligne de commande. Nous activons une expérience de gestionnaire de packages (y compris l'utilisation de gestionnaires de packages existants) pour les composants de la plate-forme .NET. Ce sera formidable pour de nombreux scénarios. La construction rapide d'un environnement de développement et CI / CD seront probablement les plus grands bénéficiaires.

Nous avions l'intention de livrer l'intégralité de la vision d'unification avec .NET 5.0, mais à la suite de la pandémie mondiale, nous avons dû nous adapter aux besoins changeants de nos clients. Nous avons travaillé avec des équipes d'entreprises du monde entier qui avaient besoin d'aide pour accélérer leur adoption des technologies cloud. Eux aussi ont dû s'adapter aux besoins changeants de leurs clients. En conséquence, nous livrons la vision à travers deux versions.

La première étape vers cette vision a été la consolidation des dépôts .NET , y compris un grand sous-ensemble de Mono. Avoir un référentiel pour le runtime et les bibliothèques pour .NET est une condition préalable à la livraison du même produit partout. Il aide également à apporter des modifications importantes qui affectent le temps d'exécution et les bibliothèques, là où il y avait auparavant des limites de dépôt. Certaines personnes craignaient qu'un gros repo ne soit plus difficile à gérer. Cela ne s'est pas avéré être le cas.

Dans la version .NET 5.0, Blazor est le meilleur exemple d'utilisation de la consolidation des dépôts et de l'unification .NET. Le runtime et les bibliothèques de Blazor WebAssembly sont désormais créés à partir du référentiel dotnet / runtime consolidé . Cela signifie que Blazor WebAssembly et Blazor sur le serveur utilisent exactement le même code pour , par exemple. Ce n'était pas le cas pour Blazor avant .NET 5.0. L'approche que nous avons adoptée pour Blazor WebAssembly est très similaire à ce que nous ferons avec Xamarin dans .NET 6.0.List<T>

Le .NET Framework reste un produit Microsoft pris en charge et continuera à être pris en charge avec chaque nouvelle version de Windows. Nous avons annoncé l'année dernière que nous avions cessé d'ajouter de nouvelles fonctionnalités à .NET Framework et que nous avions terminé d'ajouter des API .NET Framework à .NET Core . Cela signifie que le moment est venu d'envisager de déplacer vos applications .NET Framework vers .NET Core. Pour les développeurs de clients .NET Framework, Windows Forms et WPF sont pris en charge avec .NET 5.0. Nous avons entendu de nombreux développeurs dire que le portage à partir de .NET Framework est simple. Pour les développeurs de serveurs .NET Framework, vous devez adopter ASP.NET Core pour utiliser .NET 5.0. Pour les développeurs Web Forms, nous pensons que Blazoroffre une expérience de développeur similaire avec une implémentation efficace et beaucoup plus moderne. Les utilisateurs du serveur WCF et du flux de travail peuvent rechercher des projets de communauté qui prennent en charge ces frameworks . Le portage de .NET Framework vers .NET Core doc est un bon point de départ. Cela dit, garder votre application sur .NET Framework est une bonne approche si vous êtes satisfait de votre expérience.

L'équipe Windows travaille sur Project Reunion en tant que prochaine étape pour UWP et les technologies associées. Nous collaborons avec l'équipe de la Réunion pour nous assurer que .NET 5.0 et les versions ultérieures fonctionneront bien avec WinUI et WebView2. Le repo Project Reunion est le meilleur endroit pour se tenir au courant des progrès.

Passons aux nouveautés de la version 5.0.

Langages

C # 9 et F # 5 font partie de la version .NET 5.0 et sont inclus dans le SDK .NET 5.0. Visual Basic est également inclus dans le SDK 5.0. Il n'inclut pas les modifications de langue, mais a des améliorations pour prendre en charge le Visual Basic Application Framework sur .NET Core.

Les générateurs de source C # sont une nouvelle fonctionnalité importante du compilateur C #. Ils ne font pas techniquement partie de C # 9 car il n'a pas de syntaxe de langage. Consultez Nouveaux exemples de générateur de source C # pour vous aider à utiliser cette nouvelle fonctionnalité. Nous prévoyons d'utiliser davantage les générateurs de sources dans le produit .NET dans .NET 6.0 et au-delà.

Afin d'essayer la nouvelle version nous-mêmes, quelques-uns d'entre nous ont décidé de mettre à jour le repo dotnet / iot pour utiliser la nouvelle syntaxe C # 9 et cibler .NET 5.0. Les changements ont entraîné la suppression de plus de 2 000 lignes de code, simplement en adoptant une nouvelle syntaxe. Il utilise des programmes, des enregistrements, des modèles et des expressions de commutation de niveau supérieur. Il a également été mis à jour pour tirer parti de l'ensemble complet d'annotations Nullable dans les bibliothèques .NET. Nous avons également mis à jour la documentation .NET IoT . Nous allons examiner quelques exemples de ce dépôt pour explorer C # 9.

Programmes de haut niveau

Le programme led-blink est un bel exemple de programme compact de premier niveau.

using System;
using System.Device.Gpio;
using System.Threading;

var pin = 18;
var lightTime = 1000;
var dimTime = 200;

Console.WriteLine($"Let's blink an LED!");
using GpioController controller = new ();
controller.OpenPin(pin, PinMode.Output);
Console.WriteLine($"GPIO pin enabled for use: {pin}");

// turn LED on and off
while (true)
{
    Console.WriteLine($"Light for {lightTime}ms");
    controller.Write(pin, PinValue.High);
    Thread.Sleep(lightTime);

    Console.WriteLine($"Dim for {dimTime}ms");
    controller.Write(pin, PinValue.Low);
    Thread.Sleep(dimTime);
}

Vous pouvez également voir l'utilisation de type cible new, avec l'affectation à la controllern variable. Le GpioController type n'est défini que sur le côté gauche de l'affectation. Le type est déduit du côté droit. Cette nouvelle syntaxe est une alternative à var, dont le type ne s'affiche que sur le côté droit de l'affectation et est déduit du côté gauche avec  var.

Les programmes de niveau supérieur peuvent également gagner en complexité, en définissant des méthodes et en tirant parti des types définis dans le même fichier ou dans d'autres fichiers. L' exemple CharacterLcd illustre certaines de ces fonctionnalités.

Modèles logiques et de propriété

C # 9 inclut la prise en charge de nouveaux modèles. Vous pouvez voir un exemple de modèle logique dans le code suivant du capteur de gaz CCS811 .

var threshChoice = Console.ReadKey();
Console.WriteLine();
if (threshChoice.KeyChar is 'Y' or 'y')
{
   TestThresholdAndInterrupt(ccs811);
}

Un autre nouveau modèle est celui des propriétés. Vous pouvez voir plusieurs vérifications de propriétés dans mon exemple Mycroft information access 6.0 . Le code suivant est extrait de l' exemple de lecteur RFID et NFC PN532 .

if ( pollingType is null or { Length: > 15 }) { return null ; }       

     

Ce code teste si pollingType est nul ou contient plus que 15 octets.

Je veux vous montrer deux autres modèles. Le premier est un modèle logique dans le bus CAN Mcp25xxx .

public static byte GetRxBufferNumber(Address address) => address switch
{
    >= Address.RxB0D0 and <= Address.RxB0D7 => 0,
    >= Address.RxB1D0 and <= Address.RxB1D7 => 1,
    _ => throw new ArgumentException(nameof(address), $"Invalid address value {address}."),
};

Le second est un modèle logique dans Piezo Buzzer Controller .

if (element is not NoteElement noteElement)
{
    // In case it's a pause element we have only just wait desired time.
    Thread.Sleep(durationInMilliseconds);
}
else
{
    // In case it's a note element we play it.
    var frequency = GetFrequency(noteElement.Note, noteElement.Octave);
    _buzzer.PlayTone(frequency, (int)(durationInMilliseconds * 0.7));
    Thread.Sleep((int)(durationInMilliseconds * 0.3));
}

Records

C # 9 inclut un nouveau type de classe appelé enregistrement (Record). Il présente un certain nombre d'avantages par rapport aux classes régulières, dont la moitié est liée à une syntaxe plus concise. L' enregistrement suivant est tiré de la liaison du capteur RVB Bh1745 .

public record ChannelCompensationMultipliers(double Red, double Green, double Blue, double Clear);

Il est ensuite utilisé un peu plus tard dans le même fichier , avec une syntaxe familière:

ChannelCompensationMultipliers = new (2.2, 1.0, 1.8, 10.0);

Améliorations de l'annotation de nullité

Les bibliothèques .NET sont maintenant complètement annotées pour la nullité . Cela signifie que si vous activez la nullité , vous obtiendrez plus d'informations sur le type de la plate-forme pour diriger votre utilisation de la fonctionnalité. À l'heure actuelle, les documents .NET n'ont pas été entièrement annotés. Par exemple, doit être annoté pour prendre une string?, tandis que String.Split (Char []) a une annotation de char[]? . Nous espérons que cela sera bientôt résolu. Des informations complètes sont disponibles sur source.dot.net et via les recherches de métadonnées F12 dans Visual Studio.String.IsNullOrEmpty(string)string?char[]?

Les packages System.Device.Gpio et Iot.Device.Bindings (version 1.1.0 pour les deux) ont également été annotés dans le cadre de cette version, à l'aide des annotations .NET 5.0 mises à jour. Ces bibliothèques sont toutes deux multi-ciblées, cependant, nous utilisons la vue 5.0 pour produire des annotations pour toutes les cibles.

Remarque: Le code .NET Core 3.1 existant peut générer de nouveaux diagnostics (si vous avez activé la nullité) lorsque vous le recibler vers .NET 5.0, car il existe de nouvelles annotations.

Nous avons également ajouté de nouveaux types d'annotations. Il est courant pour les grandes classes d'instancier des membres d'objet dans des méthodes d'assistance appelées à partir d'un constructeur. Le compilateur C # ne peut pas suivre le flux d'appels à l'affectation d'objet. Il pensera que le membre est nul lors de la sortie du constructeur et avertira avec CS8618. L' attribut MemberNotNull résout ce problème. Vous appliquez l'attribut à la méthode d'assistance. Le compilateur verra alors que vous définissez cette valeur et réalisera que la méthode est appelée à partir d'un constructeur. MemberNotNullWhen est similaire.

Vous pouvez voir un exemple de MemberNotNulldans les capteurs de température BMxx80 avec le code suivant .

[MemberNotNull(nameof(_calibrationData))]
private void ReadCalibrationData()
{
   switch (this)
   {
         case Bme280 _:
            _calibrationData = new Bme280CalibrationData();
            _controlRegister = (byte)Bmx280Register.CTRL_MEAS;
            break;
         case Bmp280 _:
            _calibrationData = new Bmp280CalibrationData();
            _controlRegister = (byte)Bmx280Register.CTRL_MEAS;
            break;
         case Bme680 _:
            _calibrationData = new Bme680CalibrationData();
            _controlRegister = (byte)Bme680Register.CTRL_MEAS;
            break;
         default:
            throw new Exception("Bmxx80 device not correctly configured. Could not find calibraton data.");
   }

   _calibrationData.ReadFromDevice(this);
}

Le code réel utilise la compilation conditionnelle. En effet, le projet est multi-ciblé et cet attribut n'est pris en charge qu'avec .NET 5.0+. L'utilisation de l'attribut permet d'ignorer les vérifications d'exécution (dans le constructeur) qui seraient autrement nécessaires pour satisfaire les exigences de nullabilité, comme c'est le cas pour les versions antérieures de .NET .

Outils

Nous avons amélioré le concepteur Windows Forms, modifié la façon dont les frameworks cibles fonctionnent pour .NET 5.0 et les versions ultérieures, modifié la façon dont WinRT est pris en charge et apporté d'autres améliorations.

Concepteur Windows Forms

Le concepteur Windows Forms (pour .NET Core 3.1 et .NET 5.0) a été mis à jour dans Visual Studio 16.8 et prend désormais en charge tous les contrôles Windows Forms. Il prend également en charge l' interface utilisateur Telerik pour les contrôles WinForms . Le concepteur comprend toutes les fonctionnalités de concepteur que vous attendez, y compris: glisser-déposer, sélection, déplacer et redimensionner, couper / copier / coller / supprimer des contrôles, intégration avec la fenêtre Propriétés, génération d'événements et plus encore. La liaison de données et la prise en charge d'un ensemble plus large de contrôles tiers seront bientôt disponibles.

Concepteur de formulaires Windows

Pour en savoir plus, consultez la publication du concepteur Windows Forms pour .NET Core .

Framework cible .NET 5.0

Nous avons changé l'approche que nous utilisons pour les frameworks cibles avec .NET 5.0 . Le fichier de projet suivant illustre le nouveau framework cible .NET 5.0.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>

Le nouveau formulaire est plus compact et intuitif que le style que nous avons utilisé jusqu'à présent. De plus, nous étendons le framework cible pour décrire les dépendances du système d'exploitation. Ce changement est motivé par notre vision d'activer le ciblage d'iOS et d'Android avec Xamarin dans .NET 6.0

Les API de bureau Windows (y compris Windows Forms, WPF et WinRT) ne seront disponibles que lors du ciblage . Vous pouvez spécifier une version du système d'exploitation, comme ou (pour la mise à jour d'octobre 2018 de Windows ). Vous devez cibler une version de Windows 10 si vous souhaitez utiliser les API WinRT 

Les scénarios multiplateformes peuvent être un peu plus difficiles lorsque vous utilisez le nouveau TFM. System.Device.Gpio montre un modèle de gestion du framework cible Windows si vous souhaitez éviter de créer pour Windows ou de retirer des packages d'exécution Windows sur Linux, par exemple

Sommaire des modifications:

  • net5.0 est le nouveau Target Framework Moniker (TFM) pour .NET 5.0.
  • net5.0combine et remplace netcoreappet netstandard TFM.
  • net5.0prend en charge le mode de compatibilité .NET Framework
  • net5.0-windows sera utilisé pour exposer les fonctionnalités spécifiques à Windows, y compris les API Windows Forms, WPF et WinRT.
  • .NET 6.0 utilisera la même approche, avec , et ajoutera et .net6.0net6.0-iosnet6.0-android
  • Les TFM spécifiques au système d'exploitation peuvent inclure des numéros de version du système d'exploitation , comme .net6.0-ios14
  • Les API portables, comme ASP.NET Core, seront utilisables avec . Il en sera de même pour les formulaires Xamarin avec .net5.0net6.0

Les modèles de Visual Studio 16.8 ciblent toujours .NET Core 3.1, pour les applications console, WPF et Windows Forms. Les modèles ASP.NET ont été mis à jour pour prendre en charge .NET 5.0. Nous mettrons à jour les modèles dans Visual Studio 16.9 pour les modèles restants.

Interopérabilité WinRT (breaking change)

En ce qui concerne le ciblage des API Windows, nous sommes passés à un nouveau modèle de prise en charge des API WinRT dans le cadre de .NET 5.0 . Cela inclut l'appel d'API (dans les deux sens; CLR <==> WinRT), le marshaling des données entre les deux systèmes de types et l'unification des types qui sont destinés à être traités de la même manière à travers le système de types ou la limite ABI (c'est-à-dire «types projetés »; Et sont des exemples).IEnumerable<T>IIterable<T>

Le système d'interopérabilité WinRT existant a été supprimé du runtime .NET dans le cadre de .NET 5.0. C'est un changement radical. Cela signifie que les applications et les bibliothèques utilisant WinRT avec .NET Core 3.x devront être reconstruites et ne fonctionneront pas sur .NET 5.0 tel quel. Les bibliothèques qui utilisent les API WinRT devront multi-cibles pour gérer cette différence entre .NET Core 3.1 et .NET 5.0.

À l'avenir, nous nous fierons au nouvel outil CsWinRT fourni par l'équipe WinRT dans Windows. Il génère des assemblys d'interopérabilité WinRT basés sur C #, qui peuvent être fournis via NuGet. C'est exactement ce que fait l'équipe Windows, pour les API WinRT dans Windows. L'outil peut être utilisé par toute personne souhaitant utiliser WinRT (sous Windows) comme système d'interopérabilité, pour exposer les API natives aux API .NET ou .NET au code natif.

L' outil CsWinRT est logiquement similaire à tlbimp et tlbexp, bien que bien meilleur. Les outils tlb reposaient sur un grand nombre de plomberie d'interopérabilité COM dans le runtime .NET. L'outil CsWinRT repose uniquement sur les API .NET publiques. Cela dit, la fonctionnalité de pointeurs de fonction en C # 9 - et partiellement implémentée dans le runtime .NET 5.0 - était en partie inspirée par les besoins de l'outil CsWinRT.

Il y a plusieurs avantages à ce nouveau modèle d'interopérabilité WinRT:

  • Il peut être développé et amélioré indépendamment du runtime .NET.
  • Il est symétrique avec les systèmes d'interopérabilité basés sur des outils fournis pour d'autres systèmes d'exploitation, comme iOS et Android.
  • L'outil peut tirer parti d'autres fonctionnalités .NET (AOT, fonctionnalités C #, liaison IL), ce qui n'était pas une option pour le système précédent.
  • Simplifie la base de code d'exécution .NET .

Vous n'avez pas besoin d'ajouter des références NuGet pour utiliser les API WinRT. Cibler un TFM Windows 10 - dont nous venons de parler dans la section TFM .NET 5.0 précédemment - suffit. Si vous ciblez .NET Core 3.1 ou version antérieure, vous devez référencer les packages WinRT. Vous pouvez voir ce modèle dans le projet System.Device.Gpio .

Exportations natives

Nous avons eu des demandes d'activation des exportations pour les binaires natifs qui appellent du code .NET depuis longtemps. Le bloc de construction du scénario héberge la prise en charge d'API pour UnmanagedCallersOnlyAttribute .

Cette fonctionnalité est un élément de base pour créer des expériences de niveau supérieur. Aaron Robinson , de notre équipe, a travaillé sur un projet .NET Native Exports qui offre une expérience plus complète pour la publication de composants .NET en tant que bibliothèques natives. Nous recherchons des commentaires sur cette capacité pour aider à décider si l'approche doit être incluse dans le produit.

Le projet d'exportations natives .NET vous permet de:

  • Exposez les exportations natives personnalisées.
  • Ne nécessite pas de technologie d'interopérabilité de niveau supérieur comme COM.
  • Fonctionne sur plusieurs plates-formes.

Il existe des projets existants qui permettent des scénarios similaires, tels que:

Au fil des ans, nous avons vu une variété de modèles d'hébergement pour .NET dans les applications natives. @rseanhall a proposé et implémenté un nouveau modèle pour ce faire , qui tire parti de toutes les fonctionnalités d'application intégrées offertes par la couche d'hébergement d'applications .NET (en particulier le chargement des dépendances), tout en permettant d'appeler un point d'entrée personnalisé à partir du code natif. C'est parfait pour de nombreux scénarios, et on peut imaginer devenir populaire auprès des développeurs qui hébergent des composants .NET à partir d'applications natives. Cela n'existait pas avant. Merci pour la contribution, @rseanhall .

Deux PR principaux:

“Tuyau d'événements”

Event pipe est un nouveau sous-système et une nouvelle API que nous avons ajoutés dans .NET Core 2.2 pour permettre d'effectuer des analyses de performances et d'autres diagnostics sur n'importe quel système d'exploitation. Dans .NET 5.0, le canal d'événement a été étendu pour permettre aux profileurs d'écrire des événements de canal d'événement. Ce scénario est essentiel pour les profileurs d'instrumentation qui s'appuyaient auparavant sur ETW (sous Windows) pour surveiller le comportement et les performances des applications.

Les informations de charge d'assemblage sont désormais disponibles via le canal d'événements. Cette amélioration marque le début de la mise à disposition de fonctionnalités de diagnostic similaires à celles de .NET Framework, telles que Fusion Log Viewer . Vous pouvez maintenant utiliser dotnet-trace pour collecter ces informations à l'aide de la commande suivante:

dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4:4 -- ./MyApp –my-arg 1

Le flux de travail est décrit dans la documentation dotnet-trace . Vous pouvez voir les informations de chargement d'assembly pour une application de test simple.

Assemblages de trace - charges

Microsoft.Extensions.Logging

Nous avons apporté des améliorations au fournisseur de journaux de console dans la bibliothèque. Vous pouvez désormais implémenter une personnalisation pour exercer un contrôle complet sur le formatage et la colorisation de la sortie de la console. Les API du formateur permettent un formatage riche en implémentant un sous-ensemble des séquences d'échappement (prises en charge par la plupart des terminaux modernes). L'enregistreur de console peut analyser les séquences d'échappement sur des terminaux non pris en charge, ce qui vous permet de créer un formateur unique pour tous les terminaux.

En plus de la prise en charge des formateurs personnalisés, nous avons également ajouté un formateur JSON intégré qui émet des journaux JSON structurés vers la console.

Débogage de vidage

Le débogage du code managé nécessite la connaissance des objets gérés et des constructions. Le composant d'accès aux données (DAC) est un sous-ensemble du moteur d'exécution d'exécution qui a connaissance de ces constructions et peut accéder à ces objets gérés sans runtime. Les vidages de processus .NET Core collectés sous Linux peuvent désormais être analysés sous Windows à l'aide de WinDBG ou .dotnet dump analyze

Nous avons également ajouté la prise en charge de la capture de vidages ELF à partir de processus .NET exécutés sur macOS. Étant donné que ELF n'est pas le lldbformat de fichier exécutable natif (les débogueurs natifs comme ne fonctionneront pas avec ces vidages) sur macOS, nous en avons fait une fonctionnalité opt-in. Pour activer la prise en charge de la collecte de vidage sur macOS, définissez la variable d'environnement . Les décharges résultantes peuvent être analysées en utilisant .COMPlus_DbgEnableElfDumpOnMacOS=1dotnet dump analyze

Informations sur l'environnement

Comme .NET a étendu la prise en charge des nouveaux systèmes d'exploitation et architectures de puces, les gens veulent parfois un moyen d'imprimer les informations sur l'environnement. Nous avons créé un outil .NET simple qui fait cela, appelé dotnet-runtimeinfo .

Vous pouvez installer et exécuter l'outil avec les commandes suivantes.

dotnet tool install -g dotnet-runtimeinfo
dotnet-runtimeinfo

L'outil produit une sortie sous la forme suivante pour votre environnement.

**.NET information
Version: 5.0.0
FrameworkDescription: .NET 5.0.0
Libraries version: 5.0.0
Libraries hash: cf258a14b70ad9069470a108f13765e0e5988f51

**Environment information
OSDescription: Linux 5.8.6-1-MANJARO-ARM #1 SMP Thu Sep 3 22:01:08 CEST 2020
OSVersion: Unix 5.8.6.1
OSArchitecture: Arm64
ProcessorCount: 6

**CGroup info**
cfs_quota_us: -1
memory.limit_in_bytes: 9223372036854771712
memory.usage_in_bytes: 2740666368

Runtime et bibliothèques

De nombreuses améliorations ont été apportées à l'environnement d'exécution et aux bibliothèques.

Améliorations de la qualité du code dans RyuJIT

Il y a eu beaucoup d'améliorations au JIT dans cette version, dont beaucoup ont été partagées dans les précédents articles de prévisualisation .NET 5.0. Dans cet article, j'élève les changements qui sont venus de la communauté.

Garbage Collector

Les améliorations suivantes ont été apportées au GC.

Le GC expose maintenant des informations détaillées sur la collection la plus récente, via la méthode GC.GetGCMemoryInfo . La structure GCMemoryInfo fournit des informations sur la mémoire de la machine, la mémoire du tas et la collection la plus récente, ou la collection la plus récente du type de GC que vous spécifiez - GC éphémère, à blocage complet ou en arrière-plan.

Les cas d'utilisation les plus probables de l'utilisation de cette nouvelle API sont la journalisation / la surveillance ou pour indiquer à un équilibreur de chargeur qu'une machine doit être retirée de la rotation pour demander un GC complet. Il pourrait également être utilisé pour éviter les limites strictes des conteneurs en réduisant la taille des caches.

Un autre changement, petit mais percutant, a été apporté pour reporter l' reset memoryopération coûteuse aux situations à faible mémoire . Nous nous attendons à ce que ces changements de politique réduisent la latence du GC (et l'utilisation du CPU du GC en général).

Windows Arm64

Les applications .NET peuvent désormais s'exécuter en mode natif sur Windows Arm64. Cela fait suite au support que nous avons ajouté pour Linux Arm64 (support pour glibc et musl) avec .NET Core 3.0. Avec .NET 5.0, vous pouvez développer et exécuter des applications sur les appareils Windows Arm64, tels que Surface Pro X . Vous pouvez déjà exécuter des applications .NET Core et .NET Framework sur Windows Arm64, mais via l'émulation x86. C'est réalisable, mais l'exécution native d'Arm64 offre de bien meilleures performances.

Les programmes d'installation MSI pour Arm64 ont été l'un des derniers changements de cette version. Vous pouvez voir le programme d'installation du SDK .NET 5.0 dans l'image suivante.

Programme d'installation du SDK .NET 5.0 Arm64

Le SDK .NET 5.0 ne contient actuellement pas les composants Windows Desktop - Windows Forms et WPF - sur Windows Arm64. Cette modification a été initialement partagée dans le post .NET 5.0 Preview 8 . Nous espérons ajouter le pack de bureau Windows pour Windows Arm64 dans une mise à jour de maintenance 5.0. Nous n'avons actuellement pas de date à partager. Jusque-là, le SDK, la console et les applications ASP.NET Core sont pris en charge sur Windows Arm64, mais pas sur les composants Windows Desktop.

Performances de l'Arm64

Nous investissons considérablement dans l'amélioration des performances d'Arm64 depuis plus d'un an. Nous nous engageons à faire d'Arm64 une plate-forme haute performance avec .NET. Ces améliorations s'appliquent également à Windows et Linux. La portabilité et la cohérence de la plate-forme ont toujours été des caractéristiques convaincantes de .NET. Cela inclut d'offrir d'excellentes performances partout où vous utilisez .NET. Avec .NET Core 3.x, Arm64 a la parité des fonctionnalités avec x64, mais il manque certaines fonctionnalités et investissements clés en matière de performances. Nous avons résolu ce problème dans .NET 5.0, comme décrit dans Performances d'Arm64 dans .NET 5.0 .

Les améliorations:

  • Optimisations Tune JIT pour Arm64 ( exemple )
  • Activez et tirez parti des intrinsèques du matériel Arm64 ( exemple ).
  • Ajustez les algorithmes critiques pour les performances dans les bibliothèques pour Arm64 ( exemple ).

Consultez Amélioration des performances Arm64 dans .NET 5.0 pour plus de détails.

Les éléments matériels intrinsèques sont une fonctionnalité de performance de bas niveau que nous avons ajoutée dans .NET Core 3.0. À l'époque, nous avons ajouté la prise en charge des instructions et des puces x86-64. Dans le cadre de .NET 5.0, nous étendons la fonctionnalité pour prendre en charge Arm64. Le simple fait de créer les intrinsèques n'aide pas les performances. Ils doivent être utilisés dans un code critique pour les performances. Nous avons largement exploité les propriétés intrinsèques d'Arm64 dans les bibliothèques .NET de .NET 5.0. Vous pouvez également le faire dans votre propre code, bien que vous deviez vous familiariser avec les instructions du processeur pour ce faire.

Je vais vous expliquer comment les intrinsèques du matériel fonctionnent avec une analogie. Pour la plupart, les développeurs s'appuient sur des types et des API intégrés à .NET, comme ou . Ces API tirent souvent parti des API natives du système d'exploitation, via la fonctionnalité P / Invoke . P / Invoke permet une interopérabilité native haute performance et est largement utilisé dans les bibliothèques .NET à cette fin. Vous pouvez utiliser cette même fonctionnalité vous-même pour appeler des API natives. Les intrinsèques matériels sont similaires, sauf qu'au lieu d'appeler les API du système d'exploitation, ils vous permettent d'utiliser directement les instructions du processeur dans votre code. C'est à peu près équivalent à une version .NET de C ++ intrinsèquesstring.SplitHttpClient. Les intrinsèques matériels sont mieux considérés comme une fonction d'accélération matérielle du processeur. Ils offrent des avantages très tangibles et sont désormais un élément clé du substrat de performance des bibliothèques .NET, et sont responsables de nombreux avantages que vous pouvez lire dans l'article sur les performances de .NET 5.0 . En termes de comparaison avec C ++, lorsque les éléments intrinsèques .NET sont compilés AOT dans des fichiers prêts à l'emploi, les éléments intrinsèques n'ont aucune pénalité en termes de performances d'exécution.

Remarque: le compilateur Visual C ++ possède une fonctionnalité intrinsèque analogue . Vous pouvez comparer directement les intrinsèques matériels C ++ à .NET, comme vous pouvez le voir si vous recherchez _mm_i32gather_epi32sur System.Runtime.Intrinsics.X86.Avx2 , liste des intrinsèques x64 (amd64) et guide Intel Intrinsics . Vous verrez beaucoup de similitudes.

Nous faisons nos premiers gros investissements dans les performances d'Arm64 dans la version 5.0, et nous continuerons cet effort dans les versions ultérieures. Nous travaillons directement avec les ingénieurs d' Arm Holdings pour prioriser les améliorations des produits et concevoir des algorithmes qui tirent le meilleur parti de l' Armv8 ISA . Certaines de ces améliorations apporteront de la valeur à Arm32, cependant, nous n'appliquons pas d'effort unique à Arm32. Si vous utilisez un Raspberry Pi, vous apprécierez ces améliorations si vous installez la nouvelle version Arm64 du système d'exploitation Raspberry Pi.

Nous nous attendons à ce qu'Apple annonce de nouveaux ordinateurs Mac basés sur Apple Silicon à tout moment. Nous disposons déjà des premières versions de .NET 6.0 pour Apple Silicon et avons travaillé avec les ingénieurs Apple pour aider à optimiser .NET pour cette plate-forme. Nous avons également eu un engagement communautaire précoce sur Apple Silicon (Crédit @snickler ).

P95 + Latence

Nous voyons un nombre croissant de grands sites et services accessibles sur Internet hébergés sur .NET. Bien qu'il y ait beaucoup d'intérêt légitime sur la métrique des requêtes par seconde (RPS) , nous constatons qu'aucun grand propriétaire de site ne nous pose des questions à ce sujet ou n'exige des millions de RPS. Cependant, nous entendons beaucoup parler de latence, en particulier sur l'amélioration de la latence P95 ou P99 . Souvent, le nombre de machines ou de cœurs provisionnés pour un site (et le plus gros facteur de coût) est choisi en fonction de la réalisation d'une métrique P95 spécifique, par opposition à P50. Nous pensons que la latence est la véritable «métrique monétaire».

Nos amis de Stack Overflow font un excellent travail de partage de données sur leur service. L'un de leurs ingénieurs, Nick Craver, a récemment partagé les améliorations qu'il a apportées à la latence , suite au passage à .NET Core :Les objets épinglés ont représenté un défi à long terme pour les performances du GC, en particulier parce qu'ils accélèrent (ou provoquent) la fragmentation de la mémoire. Nous avons ajouté un nouveau tas GC pour les objets épinglés . Le tas d'objets épinglés est basé sur l'hypothèse qu'il y a très peu d'objets épinglés dans un processus mais que leur présence entraîne des problèmes de performances disproportionnés. Il est logique de déplacer les objets épinglés - en particulier ceux créés par les bibliothèques .NET en tant que détail d'implémentation - vers une zone unique, laissant les tas GC générationnels avec peu ou pas d'objets épinglés, et avec des performances nettement supérieures en conséquence.

Plus récemment, nous nous sommes attaqués à des défis de longue date au sein du GC. dotnet / runtime # 2795 applique une nouvelle approche à l'analyse statique GC qui évite les conflits de verrouillage lors de la détermination de la vivacité des objets de tas GC. dotnet / runtime # 25986 utilise un nouvel algorithme pour équilibrer le travail GC entre les cœurs pendant la phase de marquage du garbage collection, ce qui devrait augmenter le débit du garbage collection avec de grands tas, ce qui à son tour réduit la latence.

Amélioration des performances de compilation à plusieurs niveaux

Nous avons travaillé sur l'amélioration de la compilation à plusieurs niveaux pour plusieurs versions. Nous continuons de le considérer comme une fonctionnalité de performance critique, à la fois pour les performances de démarrage et en régime permanent. Nous avons apporté deux grandes améliorations à la compilation à plusieurs niveaux dans cette version.

Le principal mécanisme sous-jacent à la compilation à plusieurs niveaux est le comptage des appels. Une fois qu'une méthode est appelée n fois, le moteur d'exécution demande au JIT de recompiler la méthode avec une qualité supérieure. Dès nos premières analyses de performances, nous savions que le mécanisme de comptage des appels était trop lent, mais nous ne voyions pas de moyen simple de résoudre ce problème. Dans le cadre de .NET 5.0, nous avons amélioré le mécanisme de comptage des appels utilisé par la compilation JIT à plusieurs niveaux pour lisser les performances au démarrage. Dans les versions précédentes, nous avons vu des rapports de performances imprévisibles au cours des 10 à 15 premières secondes de la durée de vie du processus (principalement pour les serveurs Web). Cela devrait maintenant être résolu.

Un autre défi de performance que nous avons trouvé était l'utilisation de la compilation à plusieurs niveaux pour les méthodes avec des boucles. Le problème fondamental est que vous pouvez avoir une méthode froide (appelée une ou plusieurs fois seulement; $ lt; n) avec une boucle qui se répète plusieurs fois. Nous appelons ce scénario pathologique «méthode froide; boucle chaude ». Il est facile d'imaginer que cela se produise avec la Mainméthode d'une application. En conséquence, nous avons désactivé la compilation à plusieurs niveaux pour les méthodes avec des boucles par défaut. Au lieu de cela, nous avons permis aux applications de choisir d'utiliser la compilation à plusieurs niveaux avec des boucles. PowerShell est une application qui a choisi de le faire, après avoir constaté des améliorations de performances élevées à un chiffre dans certains scénarios.

Pour mieux traiter les méthodes avec des boucles, nous avons implémenté le remplacement sur pile (OSR) . Ceci est similaire à une fonctionnalité des machines virtuelles Java, du même nom. OSR permet au code exécuté par une méthode en cours d'exécution d'être recompilé au milieu de l'exécution de la méthode, alors que ces méthodes sont actives «sur la pile». Cette fonctionnalité est actuellement expérimentale et opt-in, et uniquement sur x64.

Pour utiliser OSR, plusieurs fonctionnalités doivent être activées. Le fichier de projet PowerShell est un bon point de départ. Vous remarquerez que la compilation à plusieurs niveaux et toutes les fonctionnalités de quick-jit sont activées. En outre, vous devez définir la COMPlus_TC_OnStackReplacementvariable d'environnement sur 1.

Vous pouvez également définir les deux variables d'environnement suivantes, en supposant que tous les autres paramètres ont leurs valeurs par défaut:

  • COMPlus_TC_QuickJitForLoops=1
  • COMPlus_TC_OnStackReplacement=1

Nous n'avons pas l'intention d'activer OSR par défaut dans .NET 5.0 et n'avons pas encore décidé si nous le prendrons en charge en production.

Prise en charge de l'ICU sous Windows

Nous utilisons la bibliothèque ICU pour la prise en charge d'Unicode et de la globalisation, auparavant uniquement sous Linux et macOS. Nous utilisons maintenant cette même bibliothèque sous Windows 10 . Ce changement rend le comportement des API de globalisation telles que la comparaison de chaînes spécifiques à la culture cohérente entre Windows 10, macOS et Linux. Nous utilisons également ICU avec Blazor WebAssembly.

Extension de System.DirectoryServices.Protocols à Linux et macOS

Nous avons ajouté la prise en charge multiplateforme pour System.DirectoryServices.Protocols . Cela inclut la prise en charge de Linux et la prise en charge de macOS . La prise en charge de Windows était préexistante.

System.DirectoryServices.Protocols est une API de niveau inférieur à System.DirectoryServices et active (ou peut être utilisée pour activer) plus de scénarios. System.DirectoryServices inclut des concepts / implémentations Windows uniquement, donc ce n'était pas un choix évident de faire du cross-platform. Les deux ensembles d'API permettent de contrôler et d'interagir avec un serveur de service d'annuaire, comme LDAP ou Active Directory .

System.Text.Json

System.Text.Jsona été considérablement amélioré dans .NET 5.0 pour améliorer les performances, la fiabilité et faciliter l'adoption par les personnes qui connaissent Newtonsoft.Json . Il inclut également la prise en charge de la désérialisation des objets JSON en enregistrements .

Si vous envisagez d'utiliser comme alternative à , vous devriez consulter le guide de migration . Le guide clarifie la relation entre ces deux API. est destiné à couvrir un grand nombre des mêmes scénarios que , mais il n'est pas destiné à remplacer ou à atteindre la parité des fonctionnalités avec la bibliothèque JSON populaire. Nous essayons de maintenir un équilibre entre les performances et la convivialité, et le biais en faveur de la performance dans nos choix de conception.System.Text.JsonNewtonsoft.JsonSystem.Text.JsonNewtonsoft.Json

HttpClient méthodes d'extension

JsonSerializerLes méthodes d'extension sont maintenant exposées HttpClientet simplifient considérablement l'utilisation de ces deux API ensemble. Ces méthodes d'extension éliminent la complexité et prennent en charge divers scénarios pour vous, notamment la gestion du flux de contenu et la validation du type de contenu multimédia. Steve Gordon explique très bien les avantages de l' envoi et de la réception de JSON à l'aide de HttpClient avec System.Net.Http.Json .

L'exemple suivant désérialise les données JSON de prévisions météorologiques dans un Forecastenregistrement, à l'aide du nouveau

using System;
using System.Net.Http;
using System.Net.Http.Json;

string serviceURL = "https://localhost:5001/WeatherForecast";
HttpClient client = new();
Forecast[] forecasts = await client.GetFromJsonAsync<Forecast[]>(serviceURL);

foreach(Forecast forecast in forecasts)
{
    Console.WriteLine($"{forecast.Date}; {forecast.TemperatureC}C; {forecast.Summary}");
}

// {"date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"temperatureF":31,"summary":"Scorching"}            
public record Forecast(DateTime Date, int TemperatureC, int TemperatureF, string Summary);
voir brutProgram.cs hébergé avec ❤par GitHub

Ce code est compact! Il repose sur des programmes et des enregistrements de niveau supérieur de C # 9 et de la nouvelle méthode d'extension. L'utilisation de et à une telle proximité pourrait vous amener à vous demander si nous allons ajouter la prise en charge des objets JSON en streaming . J'espère vraiment.GetFromJsonAsync<T>()foreachawait

Vous pouvez essayer ceci sur votre propre machine. Les commandes du SDK .NET suivantes créeront un service de prévisions météorologiques à l'aide du modèle WebAPI. Il exposera le service à l'adresse suivante par défaut: . Il s'agit de la même URL utilisée dans l'exemple.https://localhost:5001/WeatherForecast

rich@thundera ~ % dotnet new webapi -o webapi
rich@thundera ~ % cd webapi 
rich@thundera webapi % dotnet run

Assurez-vous que vous avez exécuté en premier ou la poignée de main entre le client et le serveur ne fonctionnera pas. Si vous rencontrez des problèmes, consultez Approuver le certificat de développement ASP.NET Core HTTPS .dotnet dev-certs https --trust

Vous pouvez ensuite exécuter l'exemple précédent.

rich@thundera ~ % git clone https://gist.github.com/3b41d7496f2d8533b2d88896bd31e764.git weather-forecast
rich@thundera ~ % cd weather-forecast
rich@thundera weather-forecast % dotnet run
9/9/2020 12:09:19 PM; 24C; Chilly
9/10/2020 12:09:19 PM; 54C; Mild
9/11/2020 12:09:19 PM; -2C; Hot
9/12/2020 12:09:19 PM; 24C; Cool
9/13/2020 12:09:19 PM; 45C; Balmy

Prise en charge améliorée des types immuables

Il existe plusieurs modèles pour définir des types immuables. Les disques ne sont que les plus récents. JsonSerializerprend désormais en charge les types immuables.

Dans cet exemple, vous verrez la sérialisation avec une structure immuable.

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

var json = "{"date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"temperatureF":31,"summary":"Scorching"} ";           
var options = new JsonSerializerOptions()
{
    PropertyNameCaseInsensitive = true,
    IncludeFields = true,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
var forecast = JsonSerializer.Deserialize<Forecast>(json, options);

Console.WriteLine(forecast.Date);
Console.WriteLine(forecast.TemperatureC);
Console.WriteLine(forecast.TemperatureF);
Console.WriteLine(forecast.Summary);

var roundTrippedJson = JsonSerializer.Serialize<Forecast>(forecast, options);

Console.WriteLine(roundTrippedJson);

public struct Forecast{
    public DateTime Date {get;}
    public int TemperatureC {get;}
    public int TemperatureF {get;}
    public string Summary {get;}
    [JsonConstructor]
    public Forecast(DateTime date, int temperatureC, int temperatureF, string summary) => (Date, TemperatureC, TemperatureF, Summary) = (date, temperatureC, temperatureF, summary);
}

Remarque: L'attribut JsonConstructor est requis pour spécifier le constructeur à utiliser avec les structures. Avec les classes, s'il n'y a qu'un seul constructeur, l'attribut n'est pas obligatoire. Même chose avec les enregistrements.

Il produit la sortie suivante:

rich@thundera jsonserializerimmutabletypes % dotnet run
9/6/2020 11:31:01 AM
-1
31
Scorching
{"date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"temperatureF":31,"summary":"Scorching"}

Prise en charge des enregistrements

JsonSerializer la prise en charge des enregistrements est presque la même que celle que je viens de vous montrer pour les types immuables. La différence que je veux montrer ici est la désérialisation d'un objet JSON en un enregistrement qui expose un constructeur paramétré et une propriété init facultative.

Voici le programme, y compris la définition de l'enregistrement:

using System;
using System.Text.Json;

Forecast forecast = new(DateTime.Now, 40)
{
    Summary = "Hot!"
};

string forecastJson = JsonSerializer.Serialize<Forecast>(forecast);
Console.WriteLine(forecastJson);
Forecast? forecastObj = JsonSerializer.Deserialize<Forecast>(forecastJson);
Console.Write(forecastObj);

public record Forecast (DateTime Date, int TemperatureC)
{
    public string? Summary {get; init;}
};

Il produit la sortie suivante:

rich@thundera jsonserializerrecords % dotnet run
{"Date":"2020-09-12T18:24:47.053821-07:00","TemperatureC":40,"Summary":"Hot!"}
Forecast { Date = 9/12/2020 6:24:47 PM, TemperatureC = 40, Summary = Hot! }

Amélioration de soutienDictionary<K,V>

JsonSerializerprend désormais en charge les dictionnaires avec des clés sans chaîne . Vous pouvez voir à quoi cela ressemble dans l'exemple suivant. Avec .NET Core 3.0, ce code compile mais lève un fichier NotSupportedException.

using System;
using System.Collections.Generic;
using System.Text.Json;

Dictionary<int, string> numbers = new ()
{
    {0, "zero"},
    {1, "one"},
    {2, "two"},
    {3, "three"},
    {5, "five"},
    {8, "eight"},
    {13, "thirteen"},
    {21, "twenty one"},
    {34, "thirty four"},
    {55, "fifty five"},
};

var json = JsonSerializer.Serialize<Dictionary<int, string>>(numbers);

Console.WriteLine(json);

var dictionary = JsonSerializer.Deserialize<Dictionary<int, string>>(json);

Console.WriteLine(dictionary[55]);

Il produit la sortie suivante.

rich@thundera jsondictionarykeys % dotnet run
{"0":"zero","1":"one","2":"two","3":"three","5":"five","8":"eight","13":"thirteen","21":"twenty one","34":"thirty four","55":"fifty five"}
fifty five

Prise en charge des champs

JsonSerializerprend désormais en charge les champs . Ce changement a été apporté par @YohDeadfall . Merci!

Vous pouvez voir à quoi cela ressemble dans l'exemple suivant. Avec .NET Core 3.0, la JsonSerializer sérialisation ou la désérialisation échoue avec des types qui utilisent des champs. C'est un problème pour les types existants qui ont des champs et ne peuvent pas être modifiés. Avec ce changement, ce n'est plus un problème.

using System;
using System.Text.Json;

var json = "{\"date\":\"2020-09-06T11:31:01.923395-07:00\",\"temperatureC\":-1,\"temperatureF\":31,\"summary\":\"Scorching\"} ";           
var options = new JsonSerializerOptions()
{
    PropertyNameCaseInsensitive = true,
    IncludeFields = true,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
var forecast = JsonSerializer.Deserialize<Forecast>(json, options);

Console.WriteLine(forecast.Date);
Console.WriteLine(forecast.TemperatureC);
Console.WriteLine(forecast.TemperatureF);
Console.WriteLine(forecast.Summary);

var roundTrippedJson = JsonSerializer.Serialize<Forecast>(forecast, options);

Console.WriteLine(roundTrippedJson);

public class Forecast{
    public DateTime Date;
    public int TemperatureC;
    public int TemperatureF;
    public string Summary;
}
Produit la sortie suivante : 
rich@thundera jsonserializerfields % dotnet run
9/6/2020 11:31:01 AM
-1
31
Scorching
{"date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"temperatureF":31,"summary":"Scorching"}

Préserver les références dans les graphiques d'objets JSON

JsonSerializera ajouté la prise en charge de la préservation des références (circulaires) dans les graphiques d'objets JSON. Pour ce faire, il stocke les ID qui peuvent être reconstitués lorsqu'une chaîne JSON est désérialisée en objets.

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

Employee janeEmployee = new()
{
    Name = "Jane Doe",
    YearsEmployed = 10
};

Employee johnEmployee = new()
{
    Name = "John Smith"
};

janeEmployee.Reports = new List<Employee> { johnEmployee };
johnEmployee.Manager = janeEmployee;

JsonSerializerOptions options = new()
{
    // NEW: globally ignore default values when writing null or default
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
    // NEW: globally allow reading and writing numbers as JSON strings
    NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString,
    // NEW: globally support preserving object references when (de)serializing
    ReferenceHandler = ReferenceHandler.Preserve,
    IncludeFields = true, // NEW: globally include fields for (de)serialization
    WriteIndented = true,};

string serialized = JsonSerializer.Serialize(janeEmployee, options);
Console.WriteLine($"Jane serialized: {serialized}");

Employee janeDeserialized = JsonSerializer.Deserialize<Employee>(serialized, options);
Console.Write("Whether Jane's first report's manager is Jane: ");
Console.WriteLine(janeDeserialized.Reports[0].Manager == janeDeserialized);

public class Employee
{
    // NEW: Allows use of non-public property accessor.
    // Can also be used to include fields "per-field", rather than globally with JsonSerializerOptions.
    [JsonInclude]
    public string Name { get; internal set; }

    public Employee Manager { get; set; }

    public List<Employee> Reports;

    public int YearsEmployed { get; set; }

    // NEW: Always include when (de)serializing regardless of global options
    [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
    public bool IsManager => Reports?.Count > 0;
}

Performance

JsonSerializer: les performances sont considérablement améliorées dans .NET 5.0. Stephen Toub a couvert certaines JsonSerializeraméliorations dans son article sur les améliorations des performances dans .NET 5 . J'ai également couvert Json Performance plus en détail dans le post .NET 5.0 RC1 .

Déploiement d'applications

Après avoir écrit ou mis à jour une application, vous devez la déployer pour que vos utilisateurs en bénéficient. Il peut s'agir d'un serveur Web, d'un service cloud ou d'un ordinateur client, et peut être le résultat d'un flux CI / CD utilisant un service comme Azure DevOps ou GitHub Actions .

Nous nous efforçons de fournir des capacités de déploiement de première classe qui s'alignent naturellement sur les types d'applications. Pour .NET 5.0, nous nous sommes concentrés sur l'amélioration des applications à fichier unique, la réduction de la taille du conteneur pour les builds multi-étapes de docker et une meilleure prise en charge du déploiement d'applications ClickOnce avec .NET Core.

Conteneurs

Nous considérons les conteneurs comme la tendance cloud la plus importante et avons investi considérablement dans cette modalité. Nous investissons dans des conteneurs de plusieurs manières, à plusieurs niveaux de la pile logicielle .NET. Le premier est notre investissement dans les fondamentaux, qui est de plus en plus influencé par le scénario du conteneur et par les développeurs qui déploient des applications conteneurisées.

Nous facilitons le travail avec les orchestrateurs de conteneurs. Nous avons ajouté la prise en charge d'OpenTelemetry afin que vous puissiez capturer des traces et des métriques distribuées à partir de votre application . dotnet-monitor est un nouvel outil conçu comme le principal moyen d'accéder aux informations de diagnostic à partir d'un processus .NET. En particulier, nous avons commencé à créer une variante de conteneur de dotnet-monitor que vous pouvez utiliser comme side-car d'application . Enfin, nous développons dotnet / tye comme moyen d'améliorer la productivité des développeurs de microservices, à la fois pour le développement et le déploiement dans un environnement Kubernetes.

Le runtime .NET prend désormais en charge cgroup v2 , qui, selon nous, deviendra une API importante liée aux conteneurs au-delà de 2020. Docker utilise actuellement cgroup v1 (qui est déjà pris en charge par .NET). En comparaison, cgroup v2 est plus simple, plus efficace et plus sécurisé que cgroup v1. Vous pouvez en savoir plus sur les limites des ressources cgroup et Docker dans notre mise à jour Docker 2019. Les distributions Linux et les environnements d'exécution des conteneurs sont en train d'ajouter la prise en charge de cgroup v2 . .NET 5.0 fonctionnera correctement dans les environnements cgroup v2 une fois qu'ils deviendront plus courants. Crédit Omair Majid , qui prend en charge .NET à Red Hat.

Nous publions maintenant des images Windows Server Core , en plus de Nano Server. Nous avons ajouté Server Core car nous avons entendu les commentaires de clients qui souhaitaient une image .NET entièrement compatible avec Windows Server. Si vous en avez besoin, cette nouvelle image est faite pour vous. Il est pris en charge pour la combinaison de: Windows Server 2019 Long-Term Servicing Channel (LTSC), .NET 5.0 et x64. Nous avons apporté d'autres modifications qui réduisent la taille des images Windows Server Core . Ces améliorations font une grande différence, mais ont été apportées après la sortie de Windows Server 2019. Ils bénéficieront cependant de la prochaine version de Windows Server LTSC.

Dans le cadre du passage à «.NET» comme nom de produit, nous publions désormais des images .NET Core 2.1, 3.1 et .NET 5.0 dans la famille des dépôts, au lieu de . Nous continuerons la double publication .NET Core 2.1 et 3.1 vers l'emplacement précédent tant que ces versions sont prises en charge. Les images .NET 5.0 ne seront publiées que vers les nouveaux emplacements. Veuillez mettre à jour vos déclarations et scripts en conséquence.mcr.microsoft.com/dotnetmcr.microsoft.com/dotnet/coreFROM

Dans le cadre de .NET 5.0, nous avons re-basé l'image du SDK au-dessus de l'image ASP.NET au lieu de buildpack-deps pour réduire considérablement la taille des images agrégées que vous extrayez dans des scénarios de génération en plusieurs étapes.

Cette modification présente l'avantage suivant pour les versions en plusieurs étapes, avec un exemple de fichier Dockerfile :

Coûts de construction en plusieurs étapes avec Ubuntu 20.04 Focal :

Extraire l'image Avant Après
sdk:5.0-focal 268 Mo 232 Mo
aspnet:5.0-focal 64 Mo 10 Ko (manifeste uniquement)

Économies nettes de téléchargement : 100 Mo (-30%)

Coûts de construction en plusieurs étapes avec Debian 10 Buster :

Extraire l'image Avant Après
sdk:5.0 280 Mo 218 Mo
aspnet:5.0 84 Mo 4 Ko (manifeste uniquement)

Économies nettes de téléchargement : 146 Mo (-40%)

Voir dotnet / dotnet-docker # 1814 pour plus d'informations.

Cette modification facilite les builds en plusieurs étapes, où l' image sdket l' image aspnetou que runtimevous ciblez sont la même version (nous nous attendons à ce que ce soit le cas courant). Avec ce changement, le aspnetpull (par exemple), sera un no-op, car vous aurez tiré les aspnetcouches via le sdkpull initial .

Nous avons apporté des modifications similaires pour Alpine et Nano Server . Il n'y a pas d' image pour Alpine ou Nano Server. Cependant, les images pour Alpine et Nano Server n'étaient pas précédemment construites sur l'image ASP.NET. Nous avons corrigé cela. Vous verrez des gains de taille significatifs pour Alpine et Nano Server ainsi qu'avec la version 5.0, pour les versions en plusieurs étapes.buildpack-depssdk

Applications à fichier unique

Les applications à fichier unique sont publiées et déployées sous forme de fichier unique . L'application et ses dépendances sont toutes incluses dans ce fichier. Lorsque l'application est exécutée, les dépendances sont chargées directement à partir de ce fichier en mémoire (sans pénalité de performances).

Dans .NET 5.0, les applications à fichier unique sont principalement axées sur Linux (nous en parlerons plus tard). Ils peuvent être dépendants du cadre ou autonomes. Les applications de fichier unique dépendant de Framework peuvent être très petites, en s'appuyant sur un runtime .NET installé globalement. Les applications autonomes à un seul fichier sont plus volumineuses (en raison de l'exécution du runtime), mais ne nécessitent pas l'installation du runtime .NET comme étape préalable à l'installation et fonctionneront simplement en conséquence. En général, la fonction dépendante de l'infrastructure est bonne pour les environnements de développement et d'entreprise, tandis que l'autonomie est souvent un meilleur choix pour les éditeurs de logiciels indépendants.

Nous avons produit une version d'applications à fichier unique avec .NET Core 3.1. Il regroupe les binaires dans un seul fichier pour le déploiement, puis décompresse ces fichiers dans un répertoire temporaire pour les charger et les exécuter. Il peut y avoir des scénarios où cette approche est meilleure, mais nous prévoyons que la solution que nous avons créée pour 5.0 sera préférée et une amélioration bienvenue.

Nous avons eu plusieurs obstacles à surmonter pour créer une véritable solution à fichier unique. Les tâches principales consistaient à créer un bundler d'applications plus sophistiqué et à apprendre au runtime à charger des assemblys à partir de ressources binaires. Nous avons également rencontré des obstacles que nous n'avons pas pu franchir.

Sur toutes les plateformes, nous avons un composant appelé «apphost». C'est le fichier qui devient votre exécutable, par exemple sous Windows oumyapp.exe./myappsur les plates-formes Unix. Pour les applications à fichier unique, nous avons créé un nouvel hôte d'application que nous appelons «superhost». Il a le même rôle que l'hôte d'appli standard, mais comprend également une copie liée statiquement du runtime. Le superhôte est un point de conception fondamental de notre approche de fichier unique. Ce modèle est celui que nous utilisons sous Linux avec .NET 5.0. Nous n'avons pas pu implémenter cette approche sous Windows ou macOS, en raison de diverses contraintes du système d'exploitation. Nous n'avons pas de superhôte sur Windows ou macOS. Sur ces systèmes d'exploitation, les binaires d'exécution natifs (~ 3 d'entre eux) se trouvent à côté de l'application de fichier unique (ce qui entraîne «pas un seul fichier»). Nous allons revoir cette situation dans .NET 6.0, cependant, nous nous attendons à ce que les problèmes que nous avons rencontrés restent difficiles.

Vous pouvez utiliser les commandes suivantes pour créer des applications à fichier unique.

  • Application à un seul fichier dépendante du framework:
    • dotnet publish -r linux-x64 --self-contained false /p:PublishSingleFile=true
  • Application mono-fichier autonome:
    • dotnet publish -r linux-x64 --self-contained true /p:PublishSingleFile=true

Vous pouvez également configurer la publication de fichier unique avec un fichier de projet.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <!-- The OS and CPU type you are targeting -->
    <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
    <!-- Determine self-contained or framework-dependent -->
    <SelfContained>true</SelfContained>
    <!-- Enable single file -->
    <PublishSingleFile>true</PublishSingleFile>
  </PropertyGroup>

</Project>

Vous pouvez expérimenter la découpe d'assemblage pour réduire la taille de votre application. Il peut interrompre les applications en les coupant excessivement, il est donc recommandé de tester soigneusement votre application après avoir utilisé cette fonctionnalité. Le découpage d'assembly supprime également le code natif en lecture-exécution compilé à l'avance (pour les assemblys découpés), qui est principalement destiné aux performances. Vous souhaiterez tester les performances de votre application après le découpage. Vous pouvez compiler votre application prête à exécuter après le trimmng en utilisant PublishReadyToRunproperty (et en définissant sur true) .You can ready-to-run-compile your app after trimmng by using property (and setting to ).

Remarques:

  • Les applications sont spécifiques au système d'exploitation et à l'architecture. Vous devez publier pour chaque configuration (Linux x64, Linux Arm64, Windows x64,…).
  • Les fichiers de configuration (comme ) sont inclus dans le fichier unique. Vous pouvez placer un fichier de configuration supplémentaire à côté du fichier unique, si nécessaire (éventuellement pour des tests).*.runtimeconfig.json
  • .pdbles fichiers ne sont pas inclus dans le fichier unique par défaut. Vous pouvez activer l'incorporation PDB avec la propriété.<DebugType>embed</DebugType>
  • La IncludeNativeLibrariesForSelfExtractpropriété peut être utilisée pour incorporer des binaires d'exécution natifs , sous Windows et macOS, cependant, ils doivent être décompressés dans un stockage temporaire au moment de l'exécution. Cette fonctionnalité n'est pas recommandée pour une utilisation générale.

ClickOnce

ClickOnce est une option de déploiement .NET populaire depuis de nombreuses années. Il est désormais pris en charge pour les applications Windows .NET Core 3.1 et .NET 5.0. Nous savions que de nombreuses personnes souhaiteraient utiliser ClickOnce pour le déploiement d'applications lorsque nous avons ajouté la prise en charge de Windows Forms et de WPF à .NET Core 3.0. Au cours de l'année écoulée, les équipes .NET et Visual Studio ont travaillé ensemble pour activer la publication ClickOnce, à la fois en ligne de commande et dans Visual Studio.

Nous avions deux objectifs dès le début du projet:

  • Activez une expérience familière pour ClickOnce dans Visual Studio.
  • Activez un CI / CD moderne pour la publication ClickOnce avec des flux de ligne de commande, avec MSBuild ou l'outil Mage.

Il est plus simple de vous montrer l'expérience en images.

Commençons par l'expérience Visual Studio, centrée sur la publication de projets.

Publier la cible

Le modèle de déploiement principal que nous prenons actuellement en charge est celui des applications dépendant du framework . Il est facile de prendre une dépendance sur le .NET Desktop Runtime (c'est celui qui contient WPF et Windows Forms). Votre programme d'installation ClickOnce installera le runtime .NET sur les machines des utilisateurs si nécessaire. Nous avons également l'intention de prendre en charge les applications autonomes et à fichier unique.

Prérequis .NET

Vous vous demandez peut-être si vous pouvez toujours profiter de ClickOnce hors ligne et des fonctionnalités de mise à jour. Oui, vous pouvez.

Publier les paramètres

Le grand changement avec Mage est qu'il s'agit désormais d'un outil .NET, distribué sur NuGet. Cela signifie que vous n'avez pas besoin d'installer quoi que ce soit de spécial sur votre machine. Vous avez juste besoin du SDK .NET 5.0 et vous pouvez ensuite installer Mage en tant qu'outil .NET. Vous pouvez également l'utiliser pour publier des applications .NET Framework, mais la signature SHA1 et la prise en charge de la confiance partielle ont été supprimées.

La commande d'installation de Mage suit:

dotnet tool install -g Microsoft.DotNet.Mage

Une fois que vous avez produit et distribué votre programme d'installation ClickOnce, vos utilisateurs verront les boîtes de dialogue d'installation ClickOnce familières.

Première installation de l'invite Clickonce

Vos utilisateurs verront la boîte de dialogue de mise à jour lorsque vous rendrez les mises à jour disponibles.

Mise à jour disponible

Conclusion

.NET 5.0 est une autre version importante qui devrait améliorer de nombreux aspects de votre utilisation avec .NET. Nous avons permis un large éventail d'améliorations, allant des applications à fichier unique aux performances, en passant par l'utilisation de la sérialisation Json et l'activation Arm64. Bien qu'aujourd'hui soit votre premier jour avec .NET 5.0, nous exécutons .NET 5.0 en production chez Microsoft depuis des mois. Nous sommes convaincus qu'il est prêt à être utilisé, à gérer votre entreprise et à alimenter vos applications. Les nouvelles améliorations du langage en C # 9 et F # 5 devraient rendre votre code plus expressif et plus facile à écrire. .NET 5.0 est également un excellent choix pour vos applications existantes. Dans de nombreux cas, vous pouvez effectuer une mise à niveau sans trop d'effort.

Si vous êtes intéressé par la performance, vous pourriez être intéressé par nos progrès avec les benchmarks TechEmpower . Avec le recul, vous pouvez voir que .NET Core 3.1 se porte plutôt bien avec le round 19 , le dernier round. Nous sommes impatients de voir .NET 5.0 dans le prochain round 20 . Le nouveau classement sera à surveiller lorsque la 20e manche sera finalisée et publiée.

Les améliorations apportées à .NET 5.0 sont le résultat des efforts de nombreuses personnes, travaillant en collaboration à travers le monde et dans de nombreux fuseaux horaires, sur GitHub. Merci à tous ceux qui ont contribué à cette version. Et ne vous inquiétez pas, il existe de nombreuses opportunités de contribuer. La version .NET 5.0 est arrivée à son terme, mais la prochaine version a déjà commencé .

***fin de traduction du billet de Richard***

OD : On se retrouve bientôt sur tous ces sujets, alors Stay Tuned !

Faites des heureux, partagez l'article !
blog comments powered by Disqus