Reflection e generazione di origini in System.Text.Json

Questo articolo illustra le differenze tra reflection e la generazione di origine in relazione alla serializzazione System.Text.Json. Fornisce inoltre indicazioni su come scegliere l'approccio migliore per lo scenario.

Raccolta di metadati

Per serializzare o deserializzare un tipo, JsonSerializer necessita informazioni su come accedere ai membri del tipo. JsonSerializer necessita delle informazioni seguenti:

  • Come accedere ai getter e ai campi delle proprietà per la serializzazione.
  • Come accedere a un costruttore, a setter di proprietà e ai campi per la deserializzazione.
  • Informazioni sugli attributi usati per personalizzare la serializzazione o la deserializzazione.
  • Configurazione del runtime da JsonSerializerOptions.

Queste informazioni vengono definite metadati.

Riflessione

Per impostazione predefinita, JsonSerializer raccoglie i metadati in fase di esecuzione usando reflection. Ogni volta che JsonSerializer deve serializzare o deserializzare un tipo per la prima volta, raccoglie e memorizza nella cache questi metadati. Il processo di raccolta dei metadati richiede tempo e l’uso della memoria.

Generazione di origine

In alternativa, System.Text.Json può usare la funzionalità di generazione dell'origine di C# per migliorare le prestazioni, ridurre l'utilizzo della memoria privata e facilitare il taglio dell'assembly, riducendo così le dimensioni dell'app. Inoltre, alcune API di reflection non possono essere usate nelle applicazioni AOT native, quindi è necessario usare la generazione di origine per tali app.

La generazione di origine può essere usata in due modalità:

  • Modalità basata su metadati

    Durante la compilazione, System.Text.Json raccoglie le informazioni necessarie per la serializzazione e genera file di codice sorgente che popolano i metadati del contratto JSON per i tipi richiesti.

  • Modalità Ottimizzazione della serializzazione (percorso rapido)

    Funzionalità JsonSerializer che personalizzano l'output della serializzazione, ad esempio i criteri di denominazione e la conservazione dei riferimenti, comportano un sovraccarico delle prestazioni. Nella modalità di ottimizzazione della serializzazione, System.Text.Json genera codice di serializzazione ottimizzato che usa Utf8JsonWriter direttamente. Questo codice ottimizzato o di percorso rapido aumenta la velocità effettiva di serializzazione.

    Il percorso rapido deserializzazione attualmente non è disponibile. Per altre informazioni, vedere Problema 55043 per dotnet/runtime.

La generazione di origine per System.Text.Json richiede C# 9.0 o una versione successiva.

Confronto delle funzionalità

Scegliere le modalità di reflection o generazione dell’origine in base ai vantaggi seguenti offerti da ognuno di essi:

Vantaggio Riflessione Generazione di origine
(modalità basata su metadati)
Generazione di origine
(Modalità di ottimizzazione della serializzazione)
Più semplice da codificare. ✔️
Più semplice per eseguire il debug. ✔️ ✔️
Supporta membri non pubblici. ✔️ ✔️* ✔️*
Supporta tutte le personalizzazioni di serializzazione disponibili. ✔️
Riduce il tempo di avvio. ✔️ ✔️
Riduce l'utilizzo della memoria privata. ✔️ ✔️
Elimina la reflection in fase di esecuzione. ✔️ ✔️
Facilita la riduzione delle dimensioni delle app in modo sicuro. ✔️ ✔️
Aumenta la velocità effettiva di serializzazione. ✔️

* Il generatore di origine supporta alcuni membri non pubblici, ad esempio tipi interni nello stesso assembly. † contratti generati dall'origine possono essere modificati usando l'API di personalizzazione del contratto.

Vantaggio Riflessione Generazione di origine
(modalità basata su metadati)
Generazione di origine
(Modalità di ottimizzazione della serializzazione)
Più semplice da codificare. ✔️
Più semplice per eseguire il debug. ✔️
Supporta funzioni di accesso non pubbliche. ✔️
Supporta le proprietà obbligatorie. ✔️
Supporta le proprietà solo init. ✔️
Riduce il tempo di avvio. ✔️ ✔️
Riduce l'utilizzo della memoria privata. ✔️ ✔️
Elimina la reflection in fase di esecuzione. ✔️ ✔️
Facilita la riduzione delle dimensioni delle app in modo sicuro. ✔️ ✔️
Aumenta la velocità effettiva di serializzazione. ✔️