« .NET 7 s'appuie sur la base établie par .NET 6, qui comprend un ensemble unifié de bibliothèques de base, de runtime et de SDK, une expérience de développement simplifiée et une productivité accrue des développeurs. Les principaux domaines d'intérêt de .NET 7 comprennent une meilleure prise en en charge des scénarios cloud native, des outils facilitant la mise à niveau des projets existants et la simplification de l'expérience du développeur en facilitant le travail avec les conteneurs », a écrit Jeremy Likness de l'équipe .NET à propos de cette version. En gros, .NET 7 vise à faciliter le développement d'applications cloud natives et la conteneurisation.
.NET 7 Preview 6 a été testé avec Visual Studio 17.3 Preview 3. Il est recommandé d'utiliser les builds du canal Preview ppour l’essai de .NET 7 avec les produits de la famille Visual Studio. Sous macOS, il est recommandé d'utiliser la dernière version de Visual Studio 2022 pour Mac. Voici, ci-dessous, les nouvelles fonctionnalités qu’apporte la Preview 6 de .NET 7.
Convertisseurs de type
Il existe maintenant des convertisseurs de type exposés pour les nouveaux types primitifs DateOnly, TimeOnly, Int128, UInt128 et Half.
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | namespace System.ComponentModel { public class DateOnlyConverter : System.ComponentModel.TypeConverter { public DateOnlyConverter() { } } public class TimeOnlyConverter : System.ComponentModel.TypeConverter { public TimeOnlyConverter() { } } public class Int128Converter : System.ComponentModel.BaseNumberConverter { public Int128Converter() { } } public class UInt128Converter : System.ComponentModel.BaseNumberConverter { public UInt128Converter() { } } public class HalfConverter : System.ComponentModel.BaseNumberConverter { public HalfConverter() { } } } |
Personnalisation du contrat JSON
Dans certaines situations, les développeurs qui sérialisent ou désérialisent JSON constatent qu'ils ne veulent pas ou ne peuvent pas changer les types, soit parce qu'ils proviennent d'une bibliothèque externe, soit parce que cela polluerait grandement le code, mais qu'ils ont besoin d'effectuer certains changements qui influencent la sérialisation, comme la suppression d'une propriété, la modification de la façon dont les nombres sont sérialisés, la façon dont les objets sont créés, etc. Ils sont souvent obligés d'écrire des wrappers ou des convertisseurs personnalisés, ce qui est non seulement fastidieux mais rend également la sérialisation plus lente.
La personnalisation du contrat JSON permet à l'utilisateur d'avoir un meilleur contrôle sur les types qui sont sérialisés ou désérialisés et sur la manière dont ils le sont.
Se lancer dans la personnalisation
Il y a deux façons de base pour les développeurs de « se brancher » sur la personnalisation, elles aboutissent toutes deux à l'attribution de JsonSerializerOptions.TypeInfoResolver et nécessitent l'attribution de resolver :
- Le développeur peut utiliser DefaultJsonTypeInfoResolver et ajouter son modificateur, tous les modificateurs seront appelés en série :
Code : Sélectionner tout 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26JsonSerializerOptions options = new() { TypeInfoResolver = new DefaultJsonTypeInfoResolver() { Modifiers = { (JsonTypeInfo jsonTypeInfo) => { // your modifications here, i.e.: if (jsonTypeInfo.Type == typeof(int)) { jsonTypeInfo.NumberHandling = JsonNumberHandling.AllowReadingFromString; } } } } }; Point point = JsonSerializer.Deserialize<Point>(@"{""X"":""12"",""Y"":""3""}", options); Console.WriteLine($"({point.X},{point.Y})"); // (12,3) public class Point { public int X { get; set; } public int Y { get; set; } }
- Écrire son propre résolveur personnalisé en implémentant ;
- System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver ;
- Lorsque le type n'est pas géré, le code doit retourner null ;
- IJsonTypeInfoResolver peut être combiné avec d'autres pour former un résolveur efficace qui retournera la première réponse non nulle. Par exemple, JsonTypeInfoResolver.Combine(new MyResolver(), new DefaultJsonTypeInfoResolver()).
Personnalisations
La fonctionde IJsonTypeInfoResolver est de fournir JsonTypeInfo pour toute demande de sérialiseur de type, cela ne se produira qu'une fois par type et par option. JsonTypeInfo.Kind déterminera quels boutons le développeur peut changer et est déterminé en fonction du convertisseur qui est déterminé en fonction des convertisseurs fournis aux options. Par exemple, JsonTypeInfoKind.Object signifie que des propriétés peuvent être ajoutées/modifiées tandis que JsonTypeInfoKind.None signifie qu'aucun des boutons n'est garanti d'être utilisé cela peut arriver quand le type a un convertisseur personnalisé.
JsonTypeInfo est soit créé par DefaultJsonTypeInfoResolver avec des boutons pré-remplis provenant par exemple d'attributs personnalisés, soit peut être créé de toutes pièces par l'utilisateur : JsonTypeInfo.CreateJsonTypeInfo, la création à partir de zéro signifie que l'utilisateur devra également définir JsonTypeInfo.CreateObject.
Personnalisation des propriétés
Les propriétés ne sont pertinentes que lorsque JsonTypeInfo.Kind == JsonTypeInfoKind.Object et, dans le cas de DefaultJsonTypeInfoResolver, elles seront préremplies. Elles peuvent être modifiées ou créées à l'aide de JsonTypeInfo.CreateJsonPropertyInfo et ajoutées à la liste des propriétés, par exemple, si vous obtenez une classe d'une autre bibliothèque dont les API sont bizarrement conçues et que vous ne pouvez pas les modifier :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | class MyClass { private string _name = string.Empty; public string LastName { get; set; } public string GetName() => _name; public void SetName(string name) { _name = name; } } |
Avant que cette fonctionnalité n'existe, il faut créer son propre convertisseur personnalisé pour ce type.
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | JsonSerializerOptions options = new() { TypeInfoResolver = new DefaultJsonTypeInfoResolver() { Modifiers = { ModifyTypeInfo } } }; MyClass obj = new() { LastName = "Doe" }; obj.SetName("John"); string serialized = JsonSerializer.Serialize(obj, options); // {"LastName":"Doe","Name":"John"} static void ModifyTypeInfo(JsonTypeInfo ti) { if (ti.Type != typeof(MyClass)) return; JsonPropertyInfo property = ti.CreateJsonPropertyInfo(typeof(string), "Name"); property.Get = (obj) => { MyClass myClass = (MyClass)obj; return myClass.GetName(); }; property.Set = (obj, val) => { MyClass myClass = (MyClass)obj; string value = (string)val; myClass.SetName(value); }; ti.Properties.Add(property); } |
Sérialisation conditionnelle des propriétés
Dans certains scénarios d'utilisation, il est nécessaire que certaines valeurs par défaut ne soient pas sérialisées. Par exemple, vous ne voulez pas que 0 apparaisse dans le JSON pour certaines propriétés. Il était possible de faire fonctionner ce scénario auparavant en utilisant JsonIgnoreAttribute avec JsonIgnoreCondition.WhenWritingDefault. Le problème se pose lorsque la valeur par défaut n'est pas 0 mais quelque chose de différent, par exemple -1, ou qu'elle dépend d'un paramètre externe.
Il est maintenant possible de définir son propre prédicat ShouldSerialize avec la condition de votre choix. Par exemple, disons qu'il esxite une propriété string et que vous voulez que N/A n'apparaisse pas dans le JSON :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | // string property you'd like to customize JsonPropertyInfo property = ...; property.ShouldSerialize = (obj, val) => { // in this specific example we don't use parent but it's available if needed MyClass parentObj = (MyClass)obj; string value = (string)val; return value != "N/A"; }; |
Ignorer les propriétés ayant un nom ou un type spécifique
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | var modifier = new IgnorePropertiesWithNameOrType(); modifier.IgnorePropertyWithType(typeof(SecretHolder)); modifier.IgnorePropertyWithName("IrrelevantDetail"); JsonSerializerOptions options = new() { TypeInfoResolver = new DefaultJsonTypeInfoResolver() { Modifiers = { modifier.ModifyTypeInfo } } }; ExampleClass obj = new() { Name = "Test", Secret = new SecretHolder() { Value = "MySecret" }, IrrelevantDetail = 15, }; string output = JsonSerializer.Serialize(obj, options); // {"Name":"Test"} class ExampleClass { public string Name { get; set; } public SecretHolder Secret { get; set; } public int IrrelevantDetail { get; set; } } class SecretHolder { public string Value { get; set; } } class IgnorePropertiesWithNameOrType { private List<Type> _ignoredTypes = new List<Type>(); private List<string> _ignoredNames = new List<string>(); public void IgnorePropertyWithType(Type type) { _ignoredTypes.Add(type); } public void IgnorePropertyWithName(string name) { _ignoredNames.Add(name); } public void ModifyTypeInfo(JsonTypeInfo ti) { JsonPropertyInfo[] props = ti.Properties.Where((pi) => !_ignoredTypes.Contains(pi.PropertyType) && !_ignoredNames.Contains(pi.Name)).ToArray(); ti.Properties.Clear(); foreach (var pi in props) { ti.Properties.Add(pi); } } } |
Mises à jour de l'API System.Formats.Tar
Dans la Preview 4, l'assemblage System.Formats.Tar a été introduit. Elle offre des API pour la manipulation des archives TAR. Dans la Preview 6, quelques modifications ont été apportées pour couvrir quelques cas particuliers :
Classe spécialisée Global Extended Attributes
La conception initiale supposait que seules les archives TAR PAX pouvaient contenir une seule entrée GEA (Global Extended Attributes) en première position, mais il a été découvert que les archives TAR peuvent contenir plusieurs entrées GEA, qui peuvent affecter toutes les entrées suivantes jusqu'à ce qu'elles rencontrent une nouvelle entrée GEA ou la fin de l'archive.
Il a également été découvert que les entrées GEA ne doivent pas être attendues uniquement dans les archives contenant exclusivement des entrées PAX : elles peuvent apparaître dans des archives qui mélangent des entrées de différents formats. Une nouvelle classe a donc été ajoutée pour décrire une entrée GEA :
Code : | Sélectionner tout |
1 2 3 4 5 | + public sealed partial class PaxGlobalExtendedAttributesTarEntry : PosixTarEntry + { + public PaxGlobalExtendedAttributesTarEntry(IEnumerable<KeyValuePair<string, string>> globalExtendedAttributes) { } + public IReadOnlyDictionary<string, string> GlobalExtendedAttributes { get { throw null; } } + } |
Format d'entrée, pas format d'archive
Puisqu'il a également été découvert que des entrées de différents formats peuvent être mélangées dans une seule archive TAR, l'enum TarFormat a été renommé TarEntryFormat :
Code : | Sélectionner tout |
1 2 3 4 5 | -public enum TarFormat +public enum TarEntryFormat { ... } |
Et une nouvelle propriété a été ajoutée à TarEntry pour exposer le format de l'entrée :
Code : | Sélectionner tout |
1 2 3 4 5 6 | public abstract partial class TarEntry { ... + public TarEntryFormat Format { get { throw null; } } ... } |
Changements en écriture et en lecture
La propriété Format a été supprimée de TarReader car aucune archive n'est censée avoir toutes ses entrées dans un format unique. Étant donné que les entrées GEA sont maintenant décrites avec leur propre classe spécialisée, et que plusieurs entrées de ce type peuvent être trouvées dans une seule archive, la propriété dictionnaire du TarReader a également été supprimée :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 | public sealed partial class TarReader : IDisposable { ... - public TarFormat Format { get { throw null; } } - public IReadOnlyDictionary<string, string>? GlobalExtendedAttributes { get { throw null; } } ... } |
L'ajout de la classe GEA spécialisée a également affecté TarWriter :
- le constructeur qui prenait le dictionnaire pour une seule entrée GEA en première position a été supprimé ;
- un nouveau constructeur qui ne prend que le flux et le booléen leaveOpen a été ajouté ;
- le constructeur qui prend le TarFormat a été conservé, mais l'énumération a été renommée, et une valeur par défaut a été fixée à Pax. La documentation de la méthode a été modifiée pour expliquer que le paramètre format spécifié s'applique uniquement à la méthode TarWriter.WriteEntry qui ajoute une entrée à partir d'un fichier.
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | public sealed partial class TarWriter : IDisposable { ... - public TarWriter(Stream archiveStream, IEnumerable<KeyValuePair<string, string>>? globalExtendedAttributes = null, bool leaveOpen = false) { } + public TarWriter(Stream archiveStream, bool leaveOpen = false) { } - public TarWriter(Stream archiveStream, TarFormat archiveFormat, bool leaveOpen = false) { } + public TarWriter(Stream archiveStream, TarEntryFormat format = TarEntryFormat.Pax, bool leaveOpen = false) { } public void WriteEntry(string fileName, string? entryName) { } ... } |
Création de modèles
Contraintes
La Preview 6 introduit le concept de contraintes dans les modèles .NET. Les contraintes permettent de définir le contexte dans lequel les modèles sont autorisés. Ce qui peut aider le moteur de modèles à déterminer quels modèles il doit afficher dans des commandes comme dotnet new list. Dans cette version, Microsoft a ajouté la prise en charge de trois types de contraintes :
- Système d'exploitation : qui limite les modèles en fonction du système d'exploitation de l'utilisateur ;
- Template Engine Host : qui limite les modèles en fonction de l'hôte qui exécute le Template Engine. Il s'agit généralement du .NET CLI lui-même, ou de scénarios intégrés comme la boîte de dialogue Nouveau projet dans Visual Studio/Visual Studio pour Mac ;
- Charges de travail installées : exige que la charge de travail .NET SDK spécifiée soit installée avant que le modèle ne soit disponible.
Dans tous les cas, la description de ces contraintes est aussi simple que l'ajout d'une nouvelle section de contraintes au fichier de configuration du modèle :
Code : | Sélectionner tout |
1 2 3 4 5 6 | "constraints": { "web-assembly": { "type": "workload", "args": "wasm-tools" }, } |
Actuellement, ces contraintes sont prises en charge dans le .NET CLI, et l'éauipe .NET travaille des équipes Visual Studio pour les intégrer dans les expériences de création de projets et d'éléments déjà existant.
Cette fonctionnalité poura permettre aux utilisateurs du SDK de bénéficier d'une expérience plus cohérente, quel que soit leur choix d'éditeur, Microsft espère qu'elle facilitera le pilotage des utilisateurs vers les prérequis des modèles et qu'elle aidera à désencombrer la liste des modèles pour les scénarios courants tels que dotnet new list. Dans les futures versions de .NET 7.
Paramètres multi-choix
La Preview 6 ajoute également une nouvelle capacité pour les paramètres de choix ; la possibilité pour un utilisateur de spécifier plus d'une valeur dans une seule sélection. Cette fonctionnalité peut être utilisée de la même manière qu'un enum de type Flags. Voici des exemples courants de ce type de paramètre :
- choix de plusieurs formes d'authentification sur le modèle web ;
- choix de plusieurs plateformes cibles (ios, android, web) à la fois dans les templates maui.
Pour adopter ce comportement, il suffit d'ajouter allowMultipleValues : true à la définition du paramètre dans la configuration du modèle. Ceci donne alors accès à un certain nombre de fonctions d'aide à utiliser dans le contenu du modèle pour détecter les valeurs spécifiques choisies par l'utilisateur.
Unification des codes de sortie et rapports
La Preview 6 a également unifié les codes de sortie signalés par le moteur de modèles. Cela devrait permettre aux utilisateurs qui utilisent des scripts dans leur shell de prédilection de bénéficier d'une gestion des erreurs plus cohérente. En outre, les erreurs signalées par le .NET CLI comprennent désormais un lien permettant de trouver des informations détaillées sur chaque code de sortie.
Source : Microsoft
Et vous ?
Que pensez-vous des changements et des nouveautés introduits par la Preview 6 de .NET 7 ?
Voir aussi :
Microsoft annonce .NET 7 Preview 3, la version du framework pour la création des applications, apporte une amélioration du temps de démarrage avec la fonction Write-Xor-Execute activée de 10 à 15 %
Microsoft annonce .NET 7 Preview 4, la version du framework pour la création des applications, elle corrige les bogues et comprend des MAJ
Microsoft publie le premier aperçu de .NET 7 avec des optimisations continues du compilateur JIT, de nouvelles API et la prise en charge de plus de scénarios de rechargement à chaud