Introduzione alla tecnologia "Code Snippet"

Se ritieni utile questo articolo, considera la possibilità di effettuare una donazione (il cui importo è a tua completa discrezione) tramite PayPal. Grazie.

I più recenti IDE Microsoft per .NET hanno introdotto una nuova tecnologia per aumentare la produttività degli sviluppatori, chiamata "Code Snippet". Si tratta di template per la generazione automatica dei blocchi di codice di uso più comune, facilmente richiamabili dall'ambiente di sviluppo e completamente personalizzabili.

Attualmente gli IDE che supportano la tecnologia Code Snippet sono:

  • Microsoft Visual Studio 2005

  • i prodotti "express" derivati da Microsoft Visual Studio 2005, come ad esempio Microsoft Visual C# 2005 Express Edition

Nota: in questo articolo si farà riferimento all'utilizzo dei Code Snippet in Visual Studio 2005 BETA 2. È possibile, come già successo nel passaggio di VS 2005 da BETA 1 a BETA 2, che Microsoft apporti dei cambiamenti alla tecnologia con il rilascio della versione definitiva del prodotto; per informazioni e documentazioni più complete ed aggiornate si rimanda al sito Microsoft Visual Studio.

Abbiamo a disposizione due tecniche di generazione del codice:

  • Insert Snippet (o Expansion Template) per la generazione di tipi, membri e dei costrutti del linguaggio più comuni

  • Surround With per inserire un blocco di codice selezionato in un costrutto del linguaggio

Attivare i Code Snippets

Il modo più semplice per comprendere il funzionamento degli snippet e la loro utilità è quello di provarli. Possiamo richiamare uno snippet:

  1. dal menu Edit | Intellisense, selezionando "Insert Snippet..." oppure "Surround With..."

  2. mediante shortcuts da tastiera, utilizzando le combinazioni: "Ctrl+k, Ctrl+x" oppure "Ctrl+k, Ctrl+s"

  3. dal menu contestuale attivabile con il click del tasto destro del mouse, selezionando "Insert Snippet..." oppure "Surround With..."

  4. attraverso Intellisense (attivabile anche con la combinazione di tasti "Ctrl+Barra spaziatrice"), digitando lo shortcut corrispondente ad uno snippet registrato, quindi premendo il tasto TAB per attivare l'inserimento del codice automatico (normalmente dalla finestra di Intellisense è necessario premere 2 volte il tasto TAB: la prima per selezionare lo snippet, la seconda per attivarlo)

Esempio pratico di utilizzo: Insert Snippet...

Facciamo un esempio concreto. Nel codice di una classe digitiamo prop per attivare lo snippet di creazione di una proprietà per la classe:

Selezione del Code Snippet per l'inserimento di una proprietà

Premendo due volte il tasto TAB viene inserito il codice che crea una nuova proprietà in lettura e scrittura e la relativa variabile privata d'appoggio:

Codice generato dal Code Snippet per l'inserimento di una proprietà

Si notino le porzioni evidenziate all'interno del codice generato: a noi non resta che sostituire i valori predefiniti (int per il tipo di ritorno, myVar per il nome del field interno d'appoggio e MyProperty per il nome della proprietà) con i nostri valori per avere la proprietà correttamente implementata (è possibile spostarsi agevolmente tra i vari placeholder mediante il tasto TAB)

Esempio pratico di utilizzo: Surround With...

La classe d'esempio vista non è stata inserita in un namespace: rimediamo subito, sempre utilizzando uno snippet.
Selezionamo il codice della nostra classe, quindi con il tasto destro del mouse attiviamo il menu contestuale (oppure utilizzando una delle modalità elencate in precedenza per l'attivazione dei Code Snippets):

Menu contestuale: Surround With...

Dopo aver attivato lo snippet, selezioniamo tra le cartelle disponibili (percorsi di archiviazione degli snippets) "Visual C#", quindi la voce "namespace":

Selezione del Code Snippet per l'aggiunta del namespace

Il codice della nostra classe dimostrativa è ora inserito in un namespace. Per completare l'operazione, come visto per l'inserimento della proprietà, non ci resta che sostituire il placeholder MyNamespace con lo spazio dei nomi desiderato:

Codice generato dal Code Snippet per l'aggiunta del namespace

Gestione dei Code Snippets

Microsoft mette a disposizione una serie di modelli predefiniti che coprono le esigenze più comuni. È possibile visualizzare i code snippets registrati selezionando Code Snippets Manager dal menu Tools.
Come possiamo vedere sfogliando la libreria di snippets disponibili ci accorgiamo che si tratta di semplici file XML (con estensione .snippet), presenti nella cartella "VC#\Snippets\" della directory di installazione di Visual Studio (ad esempio: "C:\Programmi\Microsoft Visual Studio 8\VC#\Snippets\"). Trattandosi di file di testo posti in un normale folder, possiamo modificare i template, crearne di nuovi partendo da zero o modificando uno di quelli già presenti: non ci resta che vedere "come sono fatti" gli snippets.

Schema dei Code Snippet

Apriamo con un editor di testo (anche il notepad, ma utilizzando Visual Studio 2005 avremo anche Intellisense) uno degli snippet più semplici: class.snippet, che crea la dichiarazione di una nuova classe:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>class</Title>
      <Shortcut>class</Shortcut>
      <Description>Code snippet for class</Description>
      <Author>Microsoft Corporation</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
        <SnippetType>SurroundsWith</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>name</ID>
          <ToolTip>Class name</ToolTip>
          <Default>MyClass</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp"><![CDATA[class $name$
  {
    $selected$$end$
  }]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

Sebbene lo schema XML completo preveda diversi elementi, di seguito ci soffermeremo solo sui nodi di maggiore interesse. Per lo schema completo si rimanda alla documentazione di Visual Studio.

Elemento Descrizione
Header Contiene informazioni generali per la definizione del Code Snippet
Title Titolo del Code Snippet
Shortcut Testo utilizzato come shortcut per l'inserimento del Code Snippet
Description Descrizione del Code Snippet
Author Autore del Code Snippet
SnippetTypes Indica in quale/i categorie rientra il Code Snippet (vedere SnippetType)
SnippetType Può assumere il valore SurroundsWith o ExpansionIndica ed indica in quale categoria il Code Snippet è disponibile
Snippet Contiene le dichiarazioni specifiche relative al codice del Code Snippet
Literal Definisce una variabile letterale utilizzata nel codice del Code Snippet. È possibile dichiarare l'ID con cui verrà richiamata, il ToolTip descrittivo, il valore di Default, il Type della variabile e la Function da eseguire quando il literal riceve il focus nell'IDE (nello snippet d'esempio - dichiarazione di una classe - gli ultimi due elementi non sono utilizzati)
Object Con una struttura analoga a Literal, definisce un elemento utilizzato nel codice dello snippet ma che è probabilmente definito all'esterno dello snippet stesso
Code Utilizzando i Literal e gli Object dichiarati, definisce il codice che verrà inserito richiamando il Code Snippet

Notiamo, nell'esempio di codice riportato sopra, che le variabili (Literal o Object) vengono richiamate nell'elemento Code racchiudendole tra due caratteri $. Se definiamo ad esempio un literal con ID = "MyLiteral" dovremo utilizzare la seguente sintassi:

$MyLiteral$

Il codice di class.snippet presenta però anche due elementi, richiamati come se fossero variabili ma... non dichiarati: $selected$ e $end$. Si tratta di due Literal predefiniti ed interpretate dall'IDE: il primo ("selected") indica la posizione iniziale del cursore per la selezione dopo che lo snippet è stato attivato, mentre "end" ne indica, come facilmente immaginabile, la posizione finale.

Creare un Code Snippet

Arrivati a questo punto, avendo un po' di dimestichezza con XML e C#, ci sarà già tutto molto chiaro e, probabilmente, sarete stupiti - come lo sono stato io - della semplicità con cui è possibile realizzare uno snippet. Siamo quindi pronti per scrivere il nostro primo Code Snippet!

Immaginiamo di voler creare un modello per la generazione del codice di valorizzazione di un DataView, ovvero che implementi in modo automatico le operazioni di:

  • creazione di una connessione a SQL Server

  • creazione di un SqlDataAdapter utilizzando un comando T-SQL

  • creazione e valorizzazione di DataSet dal SqlDataAdapter

  • valorizzazione del DataView come DefaultView della tabella del DataSet

Per parametrizzare il codice e renderlo generico, così da essere utilizzato come modello, dobbiamo definire le seguenti variabili (literal):

  • ConnectionString - per la connessione al database SQL Server

  • Sql - per l'impostazione del comando T-SQL da eseguire

  • TableName - per definire quale tabella utilizzare per la lettura dei dati

Non ci resta che creare un nuovo file di testo, chiamato dataview.snippet e inserire il seguente codice:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>DataView</Title>
      <Shortcut>dataview</Shortcut>
      <Description>Code snippet per valorizzare un DataView</Description>
      <Author>Matteo Casati</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
        <SnippetType>SurroundsWith</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>ConnectionString</ID>
          <ToolTip>Stringa di connessione al database di SQL Server</ToolTip>
          <Default>Data Source=localhost;Initial Catalog=MyDatabase;User ID=sa;Password=;</Default>
        </Literal>
        <Literal>
          <ID>Sql</ID>
          <ToolTip>Istruzione SQL da eseguire</ToolTip>
          <Default>SELECT * FROM MyTable</Default>
        </Literal>
        <Literal>
          <ID>TableName</ID>
          <ToolTip>Nome della tabella da cui leggere i valori</ToolTip>
          <Default>MyTable</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
  <![CDATA[
      
SqlConnection cn = new SqlConnection("$ConnectionString$");
string sql = "$Sql$";
SqlDataAdapter cmd = new SqlDataAdapter(sql, cn);

DataSet ds = new DataSet();
cmd.Fill(ds, "$TableName$");

DataView dv = ds.Tables["$TableName$"].DefaultView;

      ]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

In modo del tutto analogo potremo creare modelli per la generazione del codice che riteniamo "ripetitivo" e che, normalmente, scriviamo (o potremmo scrivere) facendo "copia, incolla, trova, sostituisci".

Strumenti utili

Come abbiamo visto, gli snippets sono dei normali file XML. Esistono tuttavia strumenti che ci semplificano la creazione di snippets, riducendo la possibilità di errore:

  • Visual Studio 2005: pur non fornendo un editor visuale per la generazione di snippets, fornisce il supporto Intellisense secondo lo schema XML richiesto dai Code Snippets

  • Snippy - C# Code Snippet Editor è un editor visuale per la creazione di snippets in C#

  • Snippet Editor for Visual Basic 2005 Beta 2 è un editor visuale (distribuito da Microsoft e completo di codice sorgente) per la creazione di snippets in VB.NET

Aggiungere un Code Snippet agli snippet personali

Perché i nostri snippets siano utilizzabili è possibile importarli utilizzando lo strumento "Code Snippets Manager" (dal menu Tools di Visual Studio) oppure, più semplicemente, copiarli nella cartella "My Code Snippets", situata - per gli snippets C# - in "Visual Studio\Code Snippets\VC#\My Code Snippets\" che si trova nella cartella dei documenti dell'utente corrente di Windows.

Conclusioni

I nuovi IDE Microsoft offrono un set di code snippets predefiniti. Gli snippets sono creati usando un piccolo set di elementi XML e servono per semplificare e velocizzare la scrittura dei blocchi di codice si uso più comune. In aggiunta ai code snippets predefiniti, gli sviluppatori hanno la possibilità di creare i propri template che, una volta registrati, saranno utilizzabili all'interno dell'ambiente di sviluppo.