Zalecenia dotyczące pisania szablonów tekstowych T4

Te ogólne wskazówki mogą być przydatne w przypadku generowania kodu programu lub innych zasobów aplikacji w programie Visual Studio. Nie są one stałymi regułami.

Wskazówki dotyczące szablonów T4 czasu projektowania

Szablony T4 czasu projektowania to szablony, które generują kod w projekcie programu Visual Studio w czasie projektowania. Aby uzyskać więcej informacji, zobacz Projektowanie generowania kodu w czasie projektowania przy użyciu szablonów tekstowych T4.

Generowanie zmiennych aspektów aplikacji.

Generowanie kodu jest najbardziej przydatne w przypadku tych aspektów aplikacji, które mogą ulec zmianie podczas projektu lub zmienią się między różnymi wersjami aplikacji. Oddziel te zmienne aspekty od bardziej niezmiennych aspektów, aby można było łatwiej określić, co należy wygenerować. Jeśli na przykład aplikacja udostępnia witrynę internetową, należy oddzielić standardowe funkcje obsługujące strony od logiki definiującej ścieżki nawigacji między stronami.

Zakoduj aspekty zmiennych w co najmniej jednym modelu źródłowym.

Model to plik lub baza danych, którą każdy szablon odczytuje w celu uzyskania określonych wartości dla zmiennych części kodu, które mają być generowane. Modele mogą być bazami danych, plikami XML własnego projektu, diagramów lub języków specyficznych dla domeny. Zazwyczaj jeden model jest używany do generowania wielu plików w projekcie programu Visual Studio. Każdy plik jest generowany na podstawie oddzielnego szablonu.

W projekcie można użyć więcej niż jednego modelu. Można na przykład zdefiniować model nawigacji między stronami internetowymi i oddzielny model układu stron.

Skoncentruj się na potrzebach i słownictwie użytkowników, a nie na implementacji.

Na przykład w aplikacji witryny internetowej można oczekiwać, że model będzie odwoływał się do stron internetowych i hiperlinków.

Najlepiej wybrać formę prezentacji, która odpowiada rodzajowi informacji reprezentowanych przez model. Na przykład model ścieżek nawigacji za pośrednictwem witryny internetowej może być diagramem pól i strzałek.

Przetestuj wygenerowany kod.

Użyj testów ręcznych lub automatycznych, aby sprawdzić, czy wynikowy kod działa zgodnie z wymaganiami użytkowników. Unikaj generowania testów z tego samego modelu, z którego jest generowany kod.

W niektórych przypadkach testy ogólne można wykonać bezpośrednio na modelu. Możesz na przykład napisać test, który gwarantuje, że każda strona w witrynie internetowej będzie osiągana przez nawigację z innych.

Zezwalaj na kod niestandardowy: generowanie klas częściowych.

Zezwalaj na kod pisany ręcznie oprócz wygenerowanego kodu. Nietypowe jest, że schemat generowania kodu może uwzględniać wszystkie możliwe odmiany, które mogą wystąpić. W związku z tym należy oczekiwać dodania lub zastąpienia niektórych wygenerowanych kodu. Jeśli wygenerowany materiał znajduje się w języku .NET, takim jak C# lub Visual Basic, dwie strategie są szczególnie przydatne:

  • Wygenerowane klasy powinny być częściowe. Dzięki temu można dodać zawartość do wygenerowanego kodu.

  • Klasy powinny być generowane w parach, po jednym dziedziczącym z drugiej. Klasa bazowa powinna zawierać wszystkie wygenerowane metody i właściwości, a klasa pochodna powinna zawierać tylko konstruktory. Dzięki temu kod napisany ręcznie zastępuje dowolną z wygenerowanych metod.

W innych wygenerowanych językach, takich jak XML, użyj <#@include#> dyrektywy , aby tworzyć proste kombinacje ręcznie napisanej i wygenerowanej zawartości. W bardziej złożonych przypadkach może być konieczne napisanie kroku przetwarzania końcowego, który łączy wygenerowany plik z dowolnymi ręcznie zapisanymi plikami.

Przenieś wspólne materiały do dołączania plików lub szablonów czasu wykonywania.

Aby uniknąć powtarzania podobnych bloków tekstu i kodu w wielu szablonach, użyj <#@ include #> dyrektywy . Aby uzyskać więcej informacji, zobacz T4 Include Dyrektywa.

Można również tworzyć szablony tekstu w czasie wykonywania w osobnym projekcie, a następnie wywoływać je z szablonu czasu projektowania. W tym celu użyj <#@ assembly #> dyrektywy , aby uzyskać dostęp do oddzielnego projektu.

Rozważ przeniesienie dużych bloków kodu do oddzielnego zestawu.

Jeśli masz duże bloki kodu i bloki funkcji klasy, warto przenieść część tego kodu do metod kompilowanych w osobnym projekcie. Możesz użyć <#@ assembly #> dyrektywy , aby uzyskać dostęp do kodu w szablonie. Aby uzyskać więcej informacji, zobacz T4 Assembly Directive (Dyrektywa zestawu T4).

Metody można umieścić w klasie abstrakcyjnej, którą szablon może dziedziczyć. Klasa abstrakcyjna musi dziedziczyć z Microsoft.VisualStudio.TextTemplating.TextTransformationklasy . Aby uzyskać więcej informacji, zobacz T4 Template Directive (Dyrektywa T4 template).

Generowanie kodu, a nie plików konfiguracji.

Jedną z metod pisania aplikacji zmiennej jest napisanie ogólnego kodu programu, który akceptuje plik konfiguracji. Aplikacja napisana w ten sposób jest bardzo elastyczna i może zostać ponownie skonfigurowana w przypadku zmiany wymagań biznesowych bez ponownego kompilowania aplikacji. Jednak wadą tego podejścia jest to, że aplikacja będzie działać mniej dobrze niż bardziej konkretna aplikacja. Ponadto jego kod programu będzie trudniejszy do odczytania i utrzymania, częściowo dlatego, że zawsze ma do czynienia z najbardziej ogólnymi typami.

Z kolei aplikacja, której części zmiennych są generowane przed kompilacją, może być silnie typizowana. Ułatwia to i bardziej niezawodne pisanie ręcznie napisanego kodu i integrowanie go z wygenerowanymi częściami oprogramowania.

Aby uzyskać pełną korzyść generowania kodu, spróbuj wygenerować kod programu zamiast plików konfiguracji.

Użyj folderu Wygenerowanego kodu.

Umieść szablony i wygenerowane pliki w folderze projektu o nazwie Wygenerowany kod, aby wyjaśnić, że nie są to pliki, które powinny być edytowane bezpośrednio. Jeśli utworzysz kod niestandardowy do zastąpienia lub dodania do wygenerowanych klas, umieść te klasy w folderze o nazwie Kod niestandardowy. Struktura typowego projektu wygląda następująco:

MyProject
   Custom Code
      Class1.cs
      Class2.cs
   Generated Code
      Class1.tt
          Class1.cs
      Class2.tt
          Class2.cs
   AnotherClass.cs

Wskazówki dotyczące szablonów T4 w czasie wykonywania (wstępnie przetworzonych)

Przenieś wspólny materiał do dziedziczonego szablonu.

Dziedziczenie umożliwia udostępnianie metod i bloków tekstu między szablonami tekstu T4. Aby uzyskać więcej informacji, zobacz T4 Template Directive (Dyrektywa T4 template).

Można również użyć plików dołączanych, które mają szablony czasu wykonywania.

Przenieś duże elementy kodu do klasy częściowej.

Każdy szablon czasu wykonywania generuje definicję klasy częściowej, która ma taką samą nazwę jak szablon. Możesz napisać plik kodu zawierający inną częściową definicję tej samej klasy. W ten sposób można dodawać metody, pola i konstruktory do klasy. Te elementy członkowskie mogą być wywoływane z bloków kodu w szablonie.

Zaletą tego jest to, że kod jest łatwiejszy do pisania, ponieważ funkcja IntelliSense jest dostępna. Ponadto można osiągnąć lepszą separację między prezentacją a podstawową logiką.

Na przykład w MyReportText.tt:

The total is: <#= ComputeTotal() #>

W pliku MyReportText-Methods.cs:

private string ComputeTotal() { ... }

Zezwalaj na kod niestandardowy: podaj punkty rozszerzenia.

Rozważ wygenerowanie metod wirtualnych w <blokach funkcji klasy #>+. Dzięki temu pojedynczy szablon może być używany w wielu kontekstach bez modyfikacji. Zamiast modyfikować szablon, można utworzyć klasę pochodną, która dostarcza minimalną dodatkową logikę. Klasa pochodna może być zwykłym kodem lub może być szablonem czasu wykonywania.

Na przykład w MyStandardRunTimeTemplate.tt:

This page is copyright <#= CompanyName() #>.
<#+ protected virtual string CompanyName() { return ""; } #>

W kodzie aplikacji:

class FabrikamTemplate : MyStandardRunTimeTemplate
{
  protected override string CompanyName() { return "Fabrikam"; }
}
...
  string PageToDisplay = new FabrikamTemplate().TextTransform();

Wskazówki dotyczące wszystkich szablonów T4

Oddziel zbieranie danych od generowania tekstu.

Staraj się unikać mieszania bloków obliczeniowych i tekstowych. W każdym szablonie tekstowym użyj pierwszego <bloku kodu #> , aby ustawić zmienne i wykonać złożone obliczenia. Od pierwszego bloku tekstu na końcu szablonu lub pierwszego <bloku funkcji klasy #>+ unikaj długich wyrażeń i unikaj pętli i warunkowych, chyba że zawierają bloki tekstowe. Ta praktyka ułatwia odczytywanie i konserwację szablonu.

Nie używaj plików .tt dołączanych.

Użyj innego rozszerzenia nazwy pliku, takiego jak .ttinclude w przypadku plików dołączania. Użyj .tt tylko dla plików, które mają być przetwarzane jako szablony tekstu w czasie wykonywania lub w czasie projektowania. W niektórych przypadkach program Visual Studio rozpoznaje .tt pliki i automatycznie ustawia ich właściwości do przetwarzania.

Uruchom każdy szablon jako stały prototyp.

Napisz przykład kodu lub tekstu, który chcesz wygenerować, i upewnij się, że jest on poprawny. Następnie zmień jego rozszerzenie na .tt i przyrostowo wstaw kod, który modyfikuje zawartość, odczytując model.

Rozważ użycie typiowanych modeli.

Chociaż można utworzyć schemat XML lub bazy danych dla modeli, może być przydatne utworzenie języka specyficznego dla domeny (DSL). Rozszerzenie DSL ma przewagę, że generuje klasę do reprezentowania każdego węzła w schemacie i właściwości reprezentujących atrybuty. Oznacza to, że można programować pod względem modelu biznesowego. Na przykład:

Team Members:
<# foreach (Person p in team.Members)
 { #>
    <#= p.Name #>
<# } #>

Rozważ użycie diagramów dla modeli.

Wiele modeli jest najbardziej efektywnie prezentowanych i zarządzanych po prostu jako tabel tekstowych, zwłaszcza jeśli są bardzo duże.

Jednak w przypadku niektórych rodzajów wymagań biznesowych ważne jest wyjaśnienie złożonych zestawów relacji i przepływów pracy, a diagramy są najlepszym odpowiednim medium. Zaletą diagramu jest to, że łatwo jest dyskutować z użytkownikami i innymi uczestnikami projektu. Generowanie kodu na podstawie modelu na poziomie wymagań biznesowych sprawia, że kod będzie bardziej elastyczny, gdy wymagania się zmienią.

Możesz również zaprojektować własny typ diagramu jako język specyficzny dla domeny (DSL). Kod można wygenerować na podstawie języków UML i DSL. Aby uzyskać więcej informacji, zobacz Analizowanie i modelowanie architektury.