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/