Visual Studio: Code Snippet

settembre 2, 2017
by Andrea Tosato

Visual Studio: Creazione di un code snippet

Una delle funzioni più apprezzate di Visual Studio sin dalle prime versioni è la possibilità di creare dei Code Snippet. I Code Snippet permettono di memorizzare dei segmenti di codice nei quali si inseriscono dei segnaposti. Richiamando i Code Snippet è possibile modificare il nome dei segnaposti e quindi inserire solamente il nome da noi sostituito.
L’utilità dei Code Snippet è associata a codice ripetitivo che il programmatore è costretto a inserire in molti file. Proviamo a pensare a quante proprietà e a quante classi siamo costretti a scrivere per ogni progetto.
Utilizzando la parola prop o propfull seguita dal tasto TAB si ha accesso ai due dei più usati Code Snippet del linguaggio C#.

GIF CodeSnippetProp

Per creare un Code Snippet è necessario utilizzare un file XML come il seguente.
Sono presenti 2 sezioni Header e Snippet. Nella prima sezione è possibile inserire il titolo, l’autore, la descrizione, lo Shortcut ossia la parola chiave di attivazione da Visual Studio e il tipo.

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippet Format="1.0.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <Header>
    <Title>Notified Property</Title>
    <Author>Andrea Tosato</Author>
    <Shortcut>EDIPropNot</Shortcut>
    <Description>Creazione di una propertà NotifiedPropertyChanged</Description>
    <SnippetTypes>
      <SnippetType>Expansion</SnippetType>
    </SnippetTypes>
  </Header>
  <Snippet>
    <Declarations>
      <Literal>
        <ID>Type</ID>
        <Default>string</Default>
      </Literal>
      <Literal>
        <ID>Property</ID>
        <Default>PlaceHolder</Default>
      </Literal>
    </Declarations>
    <Code Language="CSharp">
<![CDATA[
    private $Type$ _$Property$;
    [DataMember]
    [Column(Name = "$Property$")]     
    public $Type$ $Property$
    {
        get { return _$Property$; }
        set
        {
            if (_$Property$ != value)
            {
                RaiseNotifyPropertyChanging("$Property$");
                _$Property$ = value;
                RaiseNotifyPropertyChanged("$Property$");
            }
        }
    }]]>
    </Code>
  </Snippet>
</CodeSnippet>

Una volta definito lo script è necessario importarlo tramite il Code Snippet Manager che si trova in Visual Studio sotto al menu Tools.

Tipologie di Code Snippet

Esistono tre valori che possono essere usati all’interno del tag SnippetTypes:

  • SurroundsWith: consente di mettere lo snippet di codice attorno a un determinato pezzo di codice.
  • Expansion: consente di inserire il frammento di codice nel punto in cui è presente il cursore.
  • Refactoring: specifica che lo snippet di codice viene utilizzato durante il refactoring Visual C #. Il refactoring non può essere utilizzato in frammenti di codice personalizzati.

Come si può vedere, solo i primi due tipi possono essere utilizzati per definire i propri Snippets.

La sezione Snippet

La sezione Snippet è il fulcro della funzionalità descritta, in essa dobbiamo riportare il codice e i segnaposti definiti nella sezione Declarations.
Nella sezione Declaration è possibile inserire molti tag Literal. L’Id è il nome che viene utilizzato per identificare nel codice un segnaposto.
Nell’esempio precedente il segnaposto Type viene utilizzato nel codice con l’espressione $Type$ che consente allo sviluppatore di cambiarne il tipo durante l’inserimento di un nuovo snippet.

<Literal>
   <ID>Type</ID>
   <Default>string</Default>
</Literal>

L’espressione Literal può contenere dei tipi chiamati Function che ci permettono di definire il codice di una nuova funzione. Nell’esempio sotto riportato viene generata una funzione con all’interno una clausola switch-case.

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <!-- Insert Header information here. -->
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>expression</ID>
                    <ToolTip>Expression to switch on.</ToolTip>
                    <Default>switch_on</Default>
                </Literal>
                <Literal Editable="false">
                    <ID>cases</ID>
                    <Function>GenerateSwitchCases($expression$)</Function>
                    <Default>default:</Default>
                </Literal>
            </Declarations>
            <Code Language="CSharp">
                <![CDATA[
                    switch ($expression$)
                    {
                         $cases$
                    }
                ]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

Sono presenti 3 diverse tipi di funzioni:

  • GenerateSwitchCases(EnumerationLiteral): genera una funzione contenente switch-case.
  • ClassName(): sostituisce il placeholder con il nome della classe in cui è inserito lo snippet
  • SimpleTypeName( TypeName ): riduce il tipo espresso dal parametro TypeName

Riporto gli esempi delle ultime due funzioni descritte:
ClassName

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Common constructor pattern</Title> 
            <Shortcut>ctor</Shortcut> 
            <Description>Code Snippet for a constructor</Description>
            <Author>Microsoft Corporation</Author> 
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID> 
                    <Default>int</Default> 
                </Literal>
                <Literal>
                    <ID>name</ID> 
                    <Default>field</Default> 
                </Literal>
                <Literal default="true" Editable="false">
                    <ID>classname</ID> 
                    <ToolTip>Class name</ToolTip> 
                    <Function>ClassName()</Function> 
                    <Default>ClassNamePlaceholder</Default> 
                </Literal>
            </Declarations>
            <Code Language="vjsharp" Format="CData">
                <![CDATA[ 
                    public $classname$ ($type$ $name$)
                    {
                        this._$name$ = $name$;
                    }
                    private $type$ _$name$;
                ]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

SimpleTypeName

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Console_WriteLine</Title> 
            <Shortcut>cw</Shortcut> 
            <Description>Code snippet for Console.WriteLine</Description> 
            <Author>Microsoft Corporation</Author> 
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType> 
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal Editable="false">
                    <ID>SystemConsole</ID> 
                    <Function>SimpleTypeName(global::System.Console)</Function> 
                </Literal>
            </Declarations>
            <Code Language="csharp">
                <![CDATA[ 
                    $SystemConsole$.WriteLine();
                ]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

About

Senior Software Developer . NET