Ostatnio odkryłem na nowo funkcjonalność definiowania własnym szablonów kodu. Funkcjonalność ta jest bardzo często nie wykorzystywana przez programistów, ale potrafi zdziałać cuda. W pisaniu aplikacji biznesowej zawsze przychodzi taki moment, że trzeba napisać kod służący do zapisywania danych do bazy, jak równię ich odczytywania.
W takim przypadku 90% kodu jest taka sama. Po pierwsze odczytujemy numer kolumny, w której przechowywane są dane w np. SQLDataReader. A następnie budujemy na podstawie danych obiekty. W trakcie odczytu danych z bazy należy oprogramować działanie w sytuacji gdy wystąpi null. I tu najczęściej sprawdza się czy w kolumnie odczytywanej występuje wartość null. Jeśli tak to podstawia się jakąś domyślną. Jeśli nie ma nulla to odczytuje się wartość z bazy.
I tu przychodzą z pomocą snippety. Cudowne szablony kodu, które pozwalają zminimalizować ilość czasu potrzebą na implementację dostępu do bazy. Zacznijmy od pierwszej części problemu. Kod w takiej sytuacji wygląda najczęściej tak:
SQLDataReader rdr = (...)
int id_ndx = rdr.GetOrdinal("id");
int name_ndx = rdr.GetOrdinal("name");
int surname_ndx = rdr.GetOrdinal("surname");
(...)
Następnie następuje najczęściej odczyt danych:
int id = rdr.IsDBNull(id_ndx) ? 0 : $reader$.GetInt32(id_ndx); string name = rdr.IsDBNull(name_ndx) ? string.Empty : rdr.GetString(name_ndx); string surname = rdr.IsDBNull(surname_ndx) ? string.Empty : rdr.GetString(surname_ndx);
Jak widać na powyższym przykładzie znaczna część kodu się powtarza. Zacznę więc od pierwszego przypadku. Zakładając, że chcemy, aby zmienne nazywały się tak samo jak kolumny w tabeli w bazie, tylko z końcówką „_ndx” można zaproponować następujące rozwiązanie:
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>GetOrdinalFromSQL</Title>
<Shortcut>MGetOrdinal</Shortcut>
<Description>Odczyt indexu kolumny z bazy danych</Description>
<Author>Michal Jankowski</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>column</ID>
<Default>columnname</Default>
<ToolTip>Column name</ToolTip>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[int $column$_ndx = rdr.GetOrdinal("$column$");
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
A teraz krok po kroku co należy zrobić. Po pierwsze należy stworzyć plik XML o rozszerzeniu snippet. Następnie dodajemy standardowe rzeczy definiujące plik XML. Rzeczy ciekawe zaczynają się dopiero od elementu Header. W nim to definiuje się podstawowe informacje dotyczące snippetu:
- Title – tytuł,
- Shortcut – ciąg znaków, który będzie musiał zostać wprowadzony w Visual Studio aby zastosować dany snippet,
- Description – opis snippetu,
- Autor – informacje o autorze,
- SnippetTypes– tu definiuje się sposób zachowania:
- SurroundsWith – snippet może zostać zastosowany do wokół zaznaczonej części kodu,
- Expansion – snippet może być użyty w miejscu kursora,
- Refactoring – snippet jest używany w trakcie refaktoringu. Tego typu snippet nie może zostać zdefiniowany przez użytkownika.
Druga część pliku XML – element Snippet – definiują jak ma wyglądać snippet. Po pierwsze muszą zostać zadeklarowane zmienne, które będą używane w snippecie – element Declarations. W tym przypadku są dwie możliwości, zmienną można zadeklarować jako:
- wartość tekstową – Literal,
- obiekt – wtedy należy dodać sekcję Object.
Jak nazwa wskazuję, zmienne, których znamy typ powinniśmy zadeklarować jako obiekt. Dzięki temu zostanie wymuszone sprawdzanie typu wpisywanego obiektu. W naszym przykładzie nie jest to konieczne i dlatego też używane są tylko elementy Literal. Deklaracja zmiennej składa się z następujących elementów:
- identyfikatora – ID,
- wartości domyślnej jaką ma przyjąć – Default – tu należy się chwilę zastanowić i wpisać taką, która będzie najprawdopodobniej najczęściej wykorzystywana w kodzie,
- podpowiedzi – ToolTip,
- typu – Type – tylko w przypadku deklaracji zmiennej jako obiektu.
I na sam koniec wystarczy już tylko zdefiniować co dany snippet ma zrobić. Należy tylko pamiętać, że nazwę zmiennej zaczynami i kończymy znakiem $. Ciąg znaków $end$ określa miejsce gdzie znaleźć ma się kursor po wykonaniu snippetu.
Teraz pozostaje już tylko zaimportować snippet do Visual Studia (Tools – > Code Snippets Manager -> Import) i zacząć go używać. W tym celu wystarczy zacząć wpisywać tekst zdefiniowany w elemencie Shortcut. Jak tylko pojawi się nasz snippet naciskamy klawisz TAB i wpisujemy potrzebne informacje. Pomiędzy zmiennymi przejście następuje za pomocą klawisza TAB. Natomiast edycję koń czy naciśnięcie przycisku ENTER.
Z rzeczy, które zauważyłem to jest fakt, ze Visual Studio nie lubi jak są używane polskie znaki w snippetach. Nie miałem na sprawdzenie tego za dużo czasu, może pomogłaby zmiana kodowania, ale mi nie importowały się snippety, w których używałem polskich liter.
Na koniec zamieszczam jeszcze przykład snippetu do drugiej części problemu dla int:
<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>GetIntFromSQL</Title>
<Shortcut>MGetInt</Shortcut>
<Description>Odczyt int z bazy danych</Description>
<Author>Michal Jankowski</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>index</ID>
<Default>column_ndx</Default>
<ToolTip>Index</ToolTip>
</Literal>
<Literal>
<ID>reader</ID>
<Default>rdr</Default>
<ToolTip>Wprowadz nazwe SQL readera</ToolTip>
</Literal>
</Declarations>
<Code Language="csharp"><![CDATA[$reader$.IsDBNull($index$) ? 0 : $reader$.GetInt32($index$);
$selected$ $end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
Oraz jako pliki cały zestaw snippetów (dodatkowo odczyt z bazy typów: string, DateTime, double, decimal):


You might want to check out:
http://snippetdesigner.codeplex.com/