Loading...

Personnalisation des contrats JSON et injection de dépendances en C#

La personnalisation des contrats JSON et l'injection de dépendances sont des concepts clés pour le développement d'applications robustes et maintenables en C#. Cet article explore ces concepts en détail, en mettant l'accent sur leur application pratique et leurs avantages.

Personnalisation des contrats JSON avec System.Text.Json

La bibliothèque System.Text.Json en C# construit un contrat JSON pour chaque type .NET, définissant la manière dont le type doit être sérialisé et désérialisé. Ce contrat est dérivé de la forme du type, incluant ses propriétés, ses champs et son implémentation des interfaces IEnumerable ou IDictionary.

Introduction à la personnalisation des contrats JSON

À partir de .NET 7, il est possible de personnaliser ces contrats JSON pour mieux contrôler la conversion des types en JSON et inversement. Cette personnalisation offre une flexibilité accrue pour adapter la sérialisation et la désérialisation aux besoins spécifiques d'une application.

Méthodes de personnalisation

Il existe deux principales façons de personnaliser les contrats JSON :

  1. Modificateurs : Un modificateur est une Action<JsonTypeInfo> ou une méthode avec un paramètre JsonTypeInfo qui obtient l'état actuel du contrat et y apporte des modifications. Par exemple, il est possible d'itérer dans les propriétés préremplies sur le JsonTypeInfo spécifié pour trouver celle qui vous intéresse, puis modifier sa propriété JsonPropertyInfo.Get (pour la sérialisation) ou JsonPropertyInfo.Set (pour la désérialisation).
  2. Résolveurs personnalisés : Vous pouvez créer un résolveur personnalisé qui implémente la logique de personnalisation souhaitée. Il est également possible de combiner un résolveur personnalisé avec d'autres, comme le résolveur par défaut.

Utilisation de JsonTypeInfo.Kind

La propriété JsonTypeInfo.Kind indique comment le convertisseur sérialise un type donné, par exemple en tant qu'objet ou en tant que tableau, et si ses propriétés sont sérialisées. Cette propriété peut être interrogée pour déterminer les aspects du contrat JSON d'un type que vous pouvez configurer.

Lire aussi: Droit Contractuel et Force Majeure

  • Object : Le convertisseur sérialise le type dans un objet JSON et utilise ses propriétés.
  • Array : Le convertisseur sérialise le type dans un tableau JSON.
  • None : Le convertisseur ne spécifie pas comment il sérialise le type ni les propriétés JsonTypeInfo qu'il utilisera.

Exemples de personnalisation

Voici quelques exemples de personnalisation des contrats JSON :

  • Incrémentation de la valeur d'une propriété lors de la désérialisation : Un modificateur peut être utilisé pour incrémenter la valeur d'une propriété lors de la désérialisation en modifiant son délégué JsonPropertyInfo.Set. Un attribut personnalisé peut être introduit pour localiser la propriété dont la valeur doit être incrémentée.
  • Inclusion des champs privés : Par défaut, System.Text.Json ignore les propriétés et les champs privés. Un attribut à l'échelle de la classe, tel que JsonIncludePrivateFieldsAttribute, peut être ajouté pour modifier cette valeur par défaut.
  • Filtrage des propriétés par type : Il est possible de filtrer des propriétés avec un type spécifique que vous ne souhaitez pas exposer aux utilisateurs. Une méthode d'extension IList<T> peut être utilisée pour supprimer de la liste JsonTypeInfo.Properties toutes les propriétés qui ont le type spécifié.
  • Gestion des guillemets autour des valeurs numériques : Si le JSON d'entrée contient des guillemets autour de certains types numériques, mais pas pour d'autres, il est possible de modifier le comportement pour toutes les valeurs int. Avant .NET 7, il était nécessaire d'écrire un convertisseur personnalisé pour corriger ce comportement.

Avantages de la personnalisation des contrats JSON

La personnalisation des contrats JSON offre plusieurs avantages :

  • Flexibilité : Permet d'adapter la sérialisation et la désérialisation aux besoins spécifiques d'une application.
  • Contrôle : Offre un contrôle précis sur la manière dont les types sont convertis en JSON et inversement.
  • Réduction du code : Évite d'écrire des convertisseurs personnalisés pour des cas simples.
  • Amélioration de la lisibilité : Permet de rendre le code plus clair et plus facile à comprendre.

Injection de dépendances

L'injection de dépendances (ID) est un modèle de conception qui permet de réduire le couplage entre les classes et d'améliorer la testabilité et la maintenabilité du code.

Principes de l'injection de dépendances

L'injection de dépendances repose sur les principes suivants :

  • Inversion de contrôle (IoC) : Un programme qui respecte les principes de l'inversion de contrôle n'est plus totalement maître des éléments nécessaires à son fonctionnement, mais se place plutôt comme une brique faisant partie d'un tout. Il dépend d'un orchestrateur global qui va lui fournir des APIs pour communiquer avec l'extérieur.
  • Dépendances explicites : Un sous-programme doit exprimer les dépendances dont il a besoin pour fonctionner.
  • Conteneur IoC : Un conteneur IoC est utilisé pour instancier le sous-programme en prenant en compte ses dépendances.

Formes d'injection de dépendances

L'injection de dépendances peut prendre plusieurs formes :

Lire aussi: Enjeux des Smart Contracts

  • Injection par constructeur : Les dépendances sont injectées via le constructeur de la classe.
  • Injection par propriété : Les dépendances sont injectées via des propriétés de la classe.
  • Injection par champ : Les dépendances sont injectées directement dans des champs privés de la classe.

Injection de dépendances dans ASP.NET Core

Dans ASP.NET Core, l'injection de dépendances est un module principal du framework. Le conteneur IoC est représenté par l'interface IServiceCollection. Pour enregistrer un service dans la collection, il convient de définir la stratégie de gestion de son cycle de vie à adopter :

  • Instance : Vous fournissez une instance au conteneur et celui-ci la réutilisera tout le temps.
  • Transient : Une nouvelle instance est créée à chaque fois qu'elle est demandée.
  • Singleton : Une seule instance est créée pour toute la durée de vie de l'application.
  • Scoped : Une instance est créée par portée (par exemple, par requête HTTP dans une application web).

Remplacement du conteneur IoC par défaut

Il est possible de remplacer le conteneur IoC présent par défaut par une autre implémentation. Pour que ce scénario soit possible, il est nécessaire de disposer d'une implémentation des abstractions adaptées au conteneur de votre choix.

Avantages de l'injection de dépendances

L'injection de dépendances offre de nombreux avantages :

  • Réduction du couplage : Les classes sont moins dépendantes les unes des autres, ce qui facilite la maintenance et la modification du code.
  • Amélioration de la testabilité : Les dépendances peuvent être facilement remplacées par des mocks ou des stubs lors des tests unitaires.
  • Amélioration de la réutilisabilité : Les classes peuvent être réutilisées dans différents contextes sans avoir à modifier leur code.
  • Amélioration de la maintenabilité : Le code est plus facile à comprendre et à modifier, ce qui réduit les risques d'erreurs.

Combinaison de la personnalisation des contrats JSON et de l'injection de dépendances

La personnalisation des contrats JSON et l'injection de dépendances peuvent être combinées pour créer des applications plus flexibles et maintenables. Par exemple, un résolveur personnalisé de contrats JSON peut être injecté en tant que dépendance dans une classe qui effectue la sérialisation ou la désérialisation JSON. Cela permet de configurer la sérialisation et la désérialisation de manière centralisée et de les adapter aux besoins spécifiques de chaque contexte.

Objets Partiellement Formés

Le concept d'objets partiellement formés soulève des questions intéressantes en matière de conception logicielle. Un objet partiellement formé est un objet qui n'est pas entièrement initialisé et qui peut donc se trouver dans un état invalide.

Lire aussi: NFL : L'influence durable de Mike Alstott

Arguments pour et contre les objets partiellement formés

  • Arguments contre : L'idée qu'un constructeur doit toujours renvoyer un objet utilisable est profondément ancrée dans la pensée de nombreux développeurs. Si un objet n'est que partiellement formé au moment où l'on y a accès, cela peut être considéré comme une violation de ce principe. De plus, le fait d'autoriser la manipulation d'objets partiellement formés peut augmenter le risque d'erreurs, car les développeurs peuvent involontairement effectuer des opérations sur un objet dans un état invalide, ce qui peut entraîner un comportement indéfini.
  • Arguments pour : Dans certains cas, il peut être nécessaire de subdiviser la formation d'un élément complexe en plusieurs étapes, car toutes les informations nécessaires à la formation totale de cet élément ne sont pas disponibles immédiatement. De plus, dans certains contextes, comme lors de la manipulation de std::array<T, N>, il peut être pratique que T ait un constructeur par défaut sans le coût de l'initialisation.

Programmation par contrat vs programmation défensive

La discussion sur les objets partiellement formés est étroitement liée aux problématiques de la programmation par contrat par rapport à la programmation défensive. La programmation par contrat repose sur l'idée que les fonctions et les classes doivent définir des contrats clairs qui spécifient les conditions préalables, les conditions postérieures et les invariants. La programmation défensive, quant à elle, consiste à vérifier systématiquement les entrées et les sorties d'une fonction ou d'une classe afin de s'assurer qu'elles sont valides.

Défis liés aux objets partiellement formés

Le principal défi lié aux objets partiellement formés est de concilier la nécessité de laisser suffisamment de latitude à l'utilisateur pour terminer la formation de l'élément tout en l'empêchant systématiquement de manipuler cet objet d'une manière qui mènerait à la catastrophe.

Sérialisation

La sérialisation est un processus qui permet de convertir un objet ou un graphe d'objets en un flux de données qui peut être stocké ou transmis. La désérialisation est le processus inverse, qui permet de reconstruire un objet à partir d'un flux de données sérialisé.

Sérialisation en Java

En Java, la sérialisation est un procédé introduit dans le JDK version 1.1 qui permet de rendre un objet ou un graphe d'objets de la JVM persistant pour stockage ou échange et vice versa. L'objet est mis sous une forme sous laquelle il pourra être reconstitué à l'identique.

Défis de la sérialisation

La sérialisation peut poser des défis en termes de sécurité, car le format de sérialisation par défaut est connu et documenté, ce qui permet à des attaquants d'accéder aux données sensibles. De plus, la sérialisation peut limiter les possibilités de changement dans la classe, car la modification de la classe peut rendre les données sérialisées incompatibles.

tags: #c #contract #resolver #private #constructeur #exemple

Articles populaires:

Share: