Codegenerierung aus Modeling Projects – Part 2

In Part 1 der Serie habe die Grundlagen der Generierung von Code in Class-Diagrammen in Modeling Projects beschrieben. In diesem Teil geht es um die Verwendung von unterschiedlichen T4-Templates und deren Anpassung.

Die Auswahl der T4-Templates erfolgt über die Eigenschaft “Text Template Bindings”. Hier werden bei der ersten Generierung Standardtemplates für Class, Enum, Interface und Struct hinterlegt. Die Templates haben folgende Eigenschaften:

Titel Beschreibung
Name Name des Templates
Overwrite Gibt an ob die Zieldateien überschrieben werden.
ProjectPath Name des VS-Zielprojektes. Ist das Projekt nicht vorhanden, dann wird es erstellt. Hier sollte man immer das Projekt ändern, da der Standard <name_model_project>Lib.csproj nicht wirklich Sinn macht.
Target Directory Der Zielordner der Klasse. Hier kann ein fester Pfad verwendet werden. es kann aber auch die Variable {PackageStructure} verwendet werden
Target Name Der Name des erstellten Objeks. Die Variable {Name} nimmt den Name aus dem UML.
Template File Path Der Pfad zur T4-Datei.

image

Wichtig ist, dass sich diese Einstellungen durch das Model vererben. Man kann sie also an jeder Stelle (egal ob Package oder Class) überschreiben. Dazu wählt man einfach im Model Explorer das Element aus und konfiguriert die “Text Template Bindings”. So kann man ganz einfach Packages auf unterschiedliche Projekte aufteilen. Das “Root-Element” sollte immer Templates haben – ansonsten bekommt man bei jeder Generierung eine Fehlermeldung.

image

Um nun die T4-Templates anzupassen, kopieren Sie zunächst alle Dateien aus “C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\Architecture Tools\Extensibility\Templates\Text” in das Modeling-Projekt und fügen diese dem Projekt hinzu. Wichtig ist dabei alle Dokumente zu kopieren, da diese Abhängigkeiten haben. In Den “Text Template Bindings” kann man dann einfach die neuen Dateien referenzieren.

Folgende Anpassungen werde ich hier jetzt beschreiben:

  • Entfernung der Warnung
  • Platzierung der Using-Statements oberhalb des Namespaces
  • Basisnamespace für Pakete.
<#@ Include File="TemplateHeader.t4" #>
<#@ Modeling ElementType="Microsoft.VisualStudio.Uml.Classes.IClass" Processor="ModelingProcessor" ApplyStereotypes="CSharp" #>
<#@ Import Namespace="Microsoft.VisualStudio.Uml.AuxiliaryConstructs" #>
<#@ Import Namespace="Microsoft.VisualStudio.Uml.Classes" #>
<#@ Import Namespace="Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml" #>
<#@ Include File="CSharpCommentHelpers.t4" #>
<#@ Include File="CSharpHelpers.t4" #>
<#@ Output Extension=".cs" #>
<# 
    WriteAutoGeneratedWarningHeader();

    string classNamespace = GetNamespace(this.Element.Namespace);
    if(!string.IsNullOrEmpty(classNamespace))
    {
#>
namespace <#= classNamespace #>
{
<#
        PushIndent("\t");
    }

    WriteUsingStatements(this.Element);
    WriteLine("");
#>

Das Entfernen der Warnung ist ganz einfach. Man muss nur die Zeile 10: WriteAutoGeneratedWarningHeader() entfernen. Danach einfach die using statements for dem Namespace Platzieren.

<#@ Include File="TemplateHeader.t4" #>
<#@ Modeling ElementType="Microsoft.VisualStudio.Uml.Classes.IClass" Processor="ModelingProcessor" ApplyStereotypes="CSharp" #>
<#@ Import Namespace="Microsoft.VisualStudio.Uml.AuxiliaryConstructs" #>
<#@ Import Namespace="Microsoft.VisualStudio.Uml.Classes" #>
<#@ Import Namespace="Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml" #>
<#@ Include File="CSharpCommentHelpers.t4" #>
<#@ Include File="CSharpHelpers.t4" #>
<#@ Output Extension=".cs" #>
<# 
    WriteUsingStatements(this.Element);
    WriteLine("");

    string classNamespace = GetNamespace(this.Element.Namespace);
    if(!string.IsNullOrEmpty(classNamespace))
    {
#>
namespace <#= classNamespace #>
{
<#
        PushIndent("\t");
    }
#>

Um Präfixes für Namespaces wie Company und Projekt zu vergeben kann man das Property “BaseName” aus dem C# Standard Profile verwenden. Dieser wird leider per default nicht verwendet.

    WriteUsingStatements(this.Element);
    WriteLine("");

    var csharpStereotypes = this.Element.Owner.AppliedStereotypes.First(s => s.Profile == "CSharpProfile");
    var baseName = csharpStereotypes.PropertyInstances.First(s => s.Name == "BaseName").Value;

    string classNamespace = baseName + GetNamespace(this.Element.Namespace);

Das Ergebnis sieht dann wie folgt aus:

image

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyCompany.ProjectAssembly1.UI
{
	public class Class1
	{
	}
}

In der nächsten und letzten Part werde ich dann noch die Verwendung eigener Profile beschreiben. Dabei werde ich dann über ein eigenes Property und Anpassungen im T4 Eigenschaften umsetzen, die bereits INotifyPropertyChanged aufrufen.

One comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s