Evento XeDotNet sui Source Generators, una recente funzionalità contenuta nell’SDK del compilatore .NET ("Roslyn”), che consentono agli sviluppatori C# di ispezionare il codice mentre viene compilato e generare al volo nuovi file sorgente C# aggiunti alla compilazione stessa. Vedremo come usarli e quanto possono essere utili nelle nostre applicazioni
2. Codice che genera altro codice
“A Source Generator is a piece of code that runs during
compilation and can inspect your program to produce
additional source files that are compiled together with the rest
of your code”
from docs.microsoft.com
Un Source Generator è un nuovo tipo di componente C# che ti
consente di fare due cose principali:
• Recuperare un oggetto che rappresenta tutto il codice utente che
viene compilato. Questo oggetto può essere ispezionato in termini
di sintassi e i modelli semantici in fase di compilazione, proprio
come già fanno gli analizzatori di codice.
• Generare file sorgenti C# che possono essere aggiunti a al contesto
del compliatore durante il corso della compilazione. In altre parole,
puoi fornire codice sorgente aggiuntivo come input per una
compilazione mentre il codice viene compilato. Escher, Mani che disegnano
3. Why ? & use cases
Perché abbiamo bisogno di generare codice?
Questo approccio ha alcuni casi d'uso tipici:
• Dobbiamo costantemente scrivere codice standard e
potremmo automatizzarlo utilizzando SG
• Abbiamo alcuni file di dati e dobbiamo analizzarli per
avere del codice fortemente tipizzato
• Abbiamo un nostro metalinguaggio da eseguire o
compilare
• Abbiamo necessità di fare discovery di oggetti e assembly
allo start-up
• Abbiamo del codice basato sulla riflessione che potrebbe
essere lento a runtime
Il team di sviluppo .Net ha gia individuato di poter utilizzare la
teconologia dei SG, anche sul altri progetti che tipicamente
rientrano in casi d’uso tipici:
https://github.com/dotnet/roslyn/blob/main/docs/features/source-generators.md
4. .NET 6 - System.Text.Json source generator
https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/
• Maggiore velocità di serializzazione
• Tempo di avvio ridotto
• Utilizzo ridotto della memoria privata
• Rimosso l'uso runtime di System.Reflection e
System.Reflection.Emit
• Trim-compatibile per ridurre le dimensioni dell'applicazione
5. .NET 6 - Razor compiler updated to use source generators
In .NET 6 il compilatore Razor è stato
implementato utilizzando generatori
di sorgenti C#.
L'uso dei generatori di sorgenti
semplifica il compilatore Razor e
accelera notevolmente i tempi di
compilazione.
6. Source Generator
https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/
Un Source Generator è un assembly .NET Standard 2.0 caricato dal compilatore insieme a qualsiasi analizzatore di
codice(Roslyn).
È utilizzabile in ambienti in cui è possibile caricare ed eseguire componenti .NET Standard.
Compilation Runs
Source generator step
of compilation
Generated source
code added as input
tocompilation
Compilation resumes
Generate
new source
code
Analyze
source
code
Source Generator
7. Anatomia di un progetto «Source Generator»
Requisiti del progetto per il implementare un source generator:
Implementare l’interfaccia ISourceGenerator e aggiungere
l’attributo [Generator]:
Il codice generato in Visual Studio è visibile tra
gli analyzer del progetto sorgente
Viene passato al generatore il contesto
della compilazione
Initialize: tipicamente utilizzato per analizzare l'albero della
sintassi al momento della compilazione. Oppure per
inizializzare .
Execute: responsabile dell'effettiva emissione del codice
sorgente. Questo metodo aggiungerà il codice sorgente al ciclo
di compilazione e rispetto ad altre tecniche, non richiede il
riavvio della compilazione.
8. Source generator tips
Prerequisiti:
• C# 9.0+ (SDK 5.0.100+)
• Microsoft Visual Studio 16.8.0+
Limiti:
• I source generator non consentono di riscrivere/modificare
il codice sorgente dell'utente.
(È possibile solo aggiungere nuovo sorgente C# anche
sfruttando le «partial class» e i «partial method»).
• Esecuzione non ordinata, ogni generatore vedrà la stessa
compilazione di input, senza accesso ai file creati da altri
generatori di origine.
Debug:
• E’ possibile usare il debugger utilizzando il metodo
Debugger.Launch(). (Viene aperta un’altra istanza di VS)
• Con VS 2022 e il setting a livello di progetto
<IsRoslynComponent>true</IsRoslynComponent>
si può creare un profilo di debug specifico per gli Analyzer
ed effettuare il debug del progetto SG nella stessa istanza
• E’ possibile forzare la generazione effettiva dei file sorgente
e la cartella di destinazione
Deploy:
• E’ possibile distribuire il nostro SG tramite NuGet Additional Files:
9. Analyze - Compilation
Una delle parti principali della generazione del codice sorgente è interpretare alcuni input prima di generare il codice.
(Codice, File esterni, Database ecc.)
È buona prassi separare questo processo e creare un modello che verrà utilizzato nel passaggio successivo.
Uno di questi input può essere il nostro stesso
codice sorgente e tramite il contesto che ci
viene passato dal compilatore abbiamo,
accesso a due principali oggetti:
• Syntax Trees: Modello che rappresenta la
struttura (testuale) di tutto il codice
sorgente (Alberi di sintassi)
• SematicModels: Modello semantico che
contiente informazioni legate ai tipi e ai
riferimenti a partire dalla sintassi.
11. Source Generator V2 – More Performance
https://andrewlock.net/exploring-dotnet-6-part-9-source-generator-updates-incremental-generators/
Source generator updates: incremental generators: Exploring .NET Core 6 - Part 9 (andrewlock.net)
https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.md
Obiettivi:
• Consentire un approccio più dettagliato alla definizione di un generatore
• Poter far scalare i Source Generator per supportare progetti complessi in Visual Studio
• Sfruttare una cache tra i passaggi a grana al fine di ridurre il lavoro duplicato
• Supportare la generazione altri tipi di elementi oltre che al solo codice (testo)
• Coesistenza con l’implentazione base che utilizza ISourceGenerator
Incremental Generators
.Net 6
12. Materiale utile
https://github.com/amis92/csharp-source-generators
Thks to Amadeusz Sadowski (amis92)
Official documentation:
https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview
Describing the compiler feature:
https://github.com/dotnet/roslyn/blob/main/docs/features/source-generators.md
To help with generator creation:
https://github.com/dotnet/roslyn/blob/main/docs/features/source-generators.cookbook.md
Show how to implement a source:
https://github.com/dotnet/roslyn-sdk/tree/main/samples/CSharp/SourceGenerators
An online Source Generator Playground:
https://wengier.com/SourceGeneratorPlayground
A basic template for writing a C# source generator, from the Roslyn dev:
https://github.com/davidwengier/SourceGeneratorTemplate