Mit Kommentaren im C#-Code wird die Dokumentationserstellung zum Kinderspiel

Veröffentlicht: 10. Nov 2002 | Aktualisiert: 09. Nov 2004

Von Douglyss Giuliana

Entwickler hassen nichts mehr als das Schreiben von Dokumentationen - es ist öde und langweilig. Dennoch gehört die technische Dokumentation bei vielen Projekten zur Pflichtübung. Darüber hinaus würden alle Projekte bei Aktualisierungs- und Pflegemaßnahmen von den Anleitungen und Hinweisen seitens der Entwickler profitieren.

Mit C# wurde daher eine komfortable Methode zum Kommentieren von Code und zum Umwandeln dieser Kommentare in eine hilfreiche Dokumentation eingeführt. Denn C# verwendet ebenso wie die VS.NET-IDE eine XML-basierte Syntax zum Erstellen von Kommentaren. Diese Kommentare werden beim Kompilieren in einer XML-Ausgabedatei gesammelt. Und mit XSL und einfachem ASP.NET-Code wird die Umwandlung der XML-Kommentarliste in eine zur Veröffentlichung geeigneten HTML-Dokumentation zum Kinderspiel.

Auf dieser Seite

Einführung
Definition des Problems
XML-Kommentare in C#
Generieren der Dokumentation
Inlinehilfe
Verbessern der Lösung
Verwenden der Beispiele
Zusammenfassung

 

Zur Homepage von Wrox

Diesen Artikel können Sie dank freundlicher Unterstützung von Wrox auf MSDN Online lesen. Wrox ist ein Partner von MSDN Online.

 

Zur Partnerübersichtsseite von MSDN Online

Einführung

Beim Schreiben einer Dokumentation erweisen sich die meisten Entwickler als die reinsten Heuchler. Jeder besteht darauf, dass andere Entwickler ihre Objekte und Schnittstellen dokumentieren, möchten es selbst aber am liebsten umgehen. Eine gute Dokumentation beschleunigt den Entwicklungsprozess für die Nutzer von Schnittstellen und erweist sich darüber hinaus auch bei der Pflege als ungemein nützlich, allerdings ist das Schreiben einer Dokumentation öde und langweilig. Würde sich das Dokumentieren von Code nicht simpel und einfach gestalten, würden die Entwickler es nicht irgendwann während der Entwicklung einstellen. Und wir alle wissen nur zu gut, dass sich später niemand mehr damit befassen wird.

C# und die Visual Studio.NET-IDE arbeiten zusammen, um ein einfaches Kommentarerstellungssystem mithilfe von XML zu ermöglichen. Dieser Artikel beschreibt die XML-Kommentarerstellung und einige der zahlreichen Tags, die hierfür zur Verfügung stehen. Im Anschluss an diese Grundlagen werden Sie unter meiner Anleitung ein wirklich einfaches ASP.NET-Projekt unter Verwendung der System.Xml-Typen und einiger weniger XSL-Dateien gestalten. Damit können Sie die Kommentare in eine dynamische Dokumentationssite umwandeln. Zum Schluss zeige ich Ihnen dann noch einen weiteren, allerdings versteckten Vorteil dieser XML-Kommentarerstellung.

Systemanforderungen
Dieser Artikel setzt grundlegende Kenntnisse der folgenden Themenbereiche voraus:

  • Visual Studio .NET

  • C#

  • XML

  • ASP.NET

  • XSL

  • IIS

Definition des Problems

Mit C# wurde eine komfortable Methode zum Kommentieren von Code und zum Umwandeln dieser Kommentare in eine hilfreiche Dokumentation eingeführt. Zusammen mit der Visual Studio.NET-IDE stellt C# eine XML-basierte Syntax zum Kommentieren von Klassen bereit. Diese Kommentare werden beim Kompilieren des Projekts in einer XML-Ausgabedatei gesammelt. Mit XSL und einem einfachen ASP.NET-Code wird die Umwandlung der XML-Kommentarliste, in einer zur Veröffentlichung geeigneten HTML-Dokumentation, zum Kinderspiel.

In diesem Projekt demonstrieren wir,wie eine ASP.NET-Webanwendung entwickelt wird, um die Kommentare aus einem vorhandenen C#-Projekt anzuzeigen. Wir beginnen mit einer Einführung in die Kommentarerstellung unter C# und VS.NET. Im Anschluss gehen wir die vom Compiler erzeugte XML-Datei durch, dann schreiben wir für die Umwandlung der Kommentare in das HTML-Format etwas XSL und programmieren schließlich eine Webanwendung, die den Umwandlungsprozess steuert.

XML-Kommentare in C#

Die Grundlagen

C# unterstützt zwei Arten von Kommentaren: die standardmäßigen Kommentare nach Art von C++ und XML-Kommentare. XML-Kommentare unterscheiden sich in zweifacher Hinsicht von C++-Kommentaren. Zum einen beginnen XML-Kommentare mit drei Schrägstrichen (///), wohingegen C++-Kommentare mit zwei Schrägstrichen auskommen.

Zum anderen enthalten XML-Kommentare immer - wie sollte es auch anders sein - XML. In einem Projekt können beide Kommentarformen verwendet werden und beide Formen werden in der IDE farbcodiert als Kommentare dargestellt. Allerdings können nur XML-Kommentare in eine Ausgabedatei kompiliert werden.

VS.NET unterstützt Sie aktiv bei der Kommentarerstellung. Bei der Eingabe der drei Schrägstriche prüft VS.NET, ob im nachfolgenden Code die Definition eines Typen, einer Variablen oder einer Funktion erfolgt. Wenn der Kommentar einer Typendefinition oder einer Variablendeklaration vorausgeht, fügt VS.NET automatisch den folgenden XML-Anfangskommentar ein:

/// <summary>
///
/// </summary>

Sie geben Ihren Kommentar nun auf der mittleren Zeile zwischen den öffnenden und schließenden Tags ein.
Wenn der Kommentar einer Funktionsdefinition vorausgeht, ist VS.NET sogar noch hilfsbereiter. Neben der Bereitstellung des summary-Knotens prüft VS.NET, ob die Funktion Parameter übernimmt oder einen Wert zurückgibt. Wenn die Funktion Parameter übernimmt, fügt VS.NET einen param-Knoten für jeden Parameter hinzu. Wenn der Rückgabetyp der Funktion nicht "void" ist, fügt VS.NET einen returns-Knoten hinzu. Der folgende Code zeigt die von VS.NET erzeugten Kommentare für eine Memberfunktion.

/// <summary>
/// 
/// </summary>
/// <param name="i"></param>
/// <param name="j"></param>
/// <returns></returns>
private int Sum(int i, int j)
{
      return i + j;
}

Die Beschreibung der Funktion würde zwischen den summary-Tags stehen. Die Beschreibung der Parameter erfolgt zwischen den param-Tags und der Rückgabewert wird zwischen den returns-Tags erläutert.

Beachten Sie, dass die VS.NET-IDE das summary-Tag für Typen, Variablen und Funktionen einfügt, die MSDN-Dokumentation jedoch vorschlägt, das remarks-Tag für die Definition von Typen (Klassen) zu verwenden. Die Verwendung des remarks-Tags für die Klassendefinition bietet den Vorteil, dass Sie Klassen anders formatieren können als Klassenmember, für die das summary-Tag verwendet wird. Wenn Sie das remarks-Tag einsetzen möchten, sollten Sie auch das automatisch eingefügte summary-Tag durch das remarks-Tag ersetzen. Alternativ können Sie summary auch für kurze Beschreibungen und remarks für detaillierte Erläuterungen nutzen. Ein Beispiel hierzu finden Sie im Projekt User im Quellcode dieses Artikels, wobei ich mich an diese Empfehlung gehalten habe.

Die MSDN-Dokumentation weicht auch am value-Tag von der VS.NET-Implementierung ab. Laut Dokumentation soll das value-Tag für die Beschreibung von Eigenschaften verwendet werden; wohingegen VS.NET auch hierfür automatisch die summary-Tags einfügt. Dies ist im Grunde genommen eine Geschmacksfrage. Sie sollten den einmal eingeschlagenen Weg allerdings konsistent weiter verfolgen.

Tags, Tags, Tags

Bis jetzt haben Sie also die fünf grundlegenden und zugleich wichtigsten Tags kennen gelernt: remarks, summary, param, returns und value. C# unterstützt allerdings mehr als ein Dutzend weiterer Tags. Einige der nützlicheren wollen wir nun einmal näher betrachten.
In einer Dokumentation sind die Beispiele, wie eine Klasse eingesetzt oder eine Funktion aufgerufen wird, meist hilfreicher als alle weitschweifigen Erklärungen. Mithilfe des example-Tags können Sie zeigen, wie ein Typ verwendet oder eine Funktion aufgerufen wird. Ein example-Knoten enthält in der Regel auch einen code-Knoten. Mit dem code-Knoten können Sie eine Zeile oder mehrere Zeilen des Beispiels als Code auskommentieren, so dass diese anders formatiert werden können.

/// <example> This sample shows how to call the Sum method.
/// <code>
/// int i = 3;
/// int j = 2;
/// int sum = 0;
/// sum = Sum(i, j);
/// </code>
/// </example>

Die Zugriffsmöglichkeiten auf einen Typ oder ein Member erläutern, wo und von wem er bzw. es jeweils verwendet werden kann. Für die Bereitstellung dieser Informationen sollte das permission-Tag genutzt werden. Permission enthält ein einziges Attribut cref. Dies sollte die Klasse angeben, die die Zugriffsebene definiert. In den meisten Fällen ist das System.Security.PermissionSet. Sie sollten allerdings nicht vergessen, den Attributwert in Anführungszeichen zu setzen. Der Text innerhalb des Tags sollte die Zugriffsebene beschreiben. Diese Beschreibung kann so einfach wie public oder so ausführlich wie everybody can call this from anywhere sein.

/// <permission cref="System.Security.PermissionSet">
/// public
/// </permission>

Ebenso wichtig wie die Kenntnis der Rückgabewerte einer Funktion ist es, die Ausnahmebedingungen zu kennen, die möglicherweise ausgegeben werden. Sie können zwar in der Headerdatei oder in der Typenbibliothek viel über einen Typen oder ein Member erfahren, Sie müssen jedoch auf den Code zugreifen, um mögliche Ausnahmebedingungen entdecken zu können. Das exception-Tag gibt die Ausnahmebedingungen an, die im Zuge eines Funktionsaufrufs ausgegeben werden können. Wenn mehr als eine Ausnahmebedingung ausgegeben werden kann, sind auch mehrere exception-Tags zulässig.

Im exception-Tag wird das Attribut cref verwendet, um die Art der Ausnahmebedingung anzugeben. Cref stellt einen Verweis auf ein vorhandenes Codeelement bereit und der Compiler überprüft die Existenz des Verweises. Bei einer Ausnahmebedingung ist dies in der Regel System.Exception oder etwas, was von System.Exception abgeleitet wird. Darüber hinaus kann im Tag auch eine Beschreibung der Ausnahme erfolgen, bzw. können die Umstände aufgeführt werden, unter denen die Ausnahmebedingung ausgegeben wird.

/// <exception cref="System.Exception">
/// Thrown any time we are out of memory or fail to write to the disk.
/// </exception>

Nun noch ein weiteres Tag, dann befassen wir uns mit der interessanteren Seite der Thematik. Am Ende jedes Referenzartikels in MSDN finden Sie eine Liste der verwandten Themen. Um ein verwandtes Thema anzugeben und um einen direkten Link hierauf zu ermöglichen, kann das seealso-Tag verwendet werden. Setzen Sie das seealso-Tag in den summary-Knoten. Das Attribut cref gibt den Typen oder das Member an, auf den bzw. das verwiesen werden soll, wie Sum im vorstehenden Beispiel und muss im Projekt daher ebenfalls zur Verfügung stehen. Anders als bei den meisten Tags ist es wenig sinnvoll, weitere Erläuterungen in diesen Knoten aufzunehmen.

/// <seealso cref="Sum" />

Die XML-Ausgabedatei

Das Kompilieren der XML-Kommentare in eine Ausgabedatei ist einfach. Öffnen Sie zunächst ein vorhandenes C#-Projekt, oder verwenden Sie das Projekt User aus dem Codedownload zu diesem Artikel. Öffnen Sie dann das Fenster Properties, indem Sie Project aus dem Menü wählen und dann auf Properties klicken (im Projektmappen-Explorer können Sie alternativ auch mit der rechten Maustaste auf den Projektnamen klicken und dann Properties auswählen). Klicken Sie im nun angezeigten Dialogfeld Property Pages auf der linken Seite auf Configuration Properties. Wählen Sie Build direkt unter Configuration Properties. Suchen Sie jetzt auf der rechten Seite unter Outputs nach XML Documentation File. Dieser Wert sollte auf den Namen der Datei festgelegt werden, die die extrahierten XML-Kommentare enthalten soll. Beachten Sie, dass der Pfad relativ zum Pfad des Projekts ist. Bei einem leeren Wert werden keine XML-Kommentare ausgegeben. Klicken Sie auf OK, und schon kann es losgehen.

Bild01

Wenn Sie das Projekt nun entwickeln, wird die vorstehend angegebene XML-Datei erzeugt und mit den XML-Kommentaren aus dem Projekt gefüllt. Wenn das Projekt aufgrund auftretender Fehler nicht programmiert werden kann, wird auch die Ausgabedatei mit den XML-Kommentaren nicht erstellt. Im Folgenden finden Sie ein Beispiel für eine Kommentardatei. (Siehe UserDoc.xml im Codedownload.)

<?xml version="1.0" ?> 
<doc> 
<assembly> 
<name>User</name> 
</assembly> 
<members> 
<member name="T:UserSecurity.User"> 
<remarks>The User class is used for all login functionality. This include login with username 
and password, changing password, and "remembering" password with hint question and 
answer.</remarks> 
</member> 
<member name="F:UserSecurity.User._username"> 
<summary>The username associated with the current user.</summary> 
</member> 
<member name="M:UserSecurity.User.Login(System.String,System.String)"> 
<summary> 
Attempts to log in the user using the username and password provided. If the username and password
 match an existing account, the login is successful. 
<seealso cref="M:UserSecurity.User.ChangePassword(System.String,System.String)" /> 
</summary> 
<param name="username">Username on account to log in.</param> 
<param name="password">Password associated with username.</param> 
<returns>True = login was successful. False = login failed.</returns> 
<permission cref="T:System.Security.PermissionSet">public</permission> 
<exception cref="T:System.Data.SqlClient.SqlException">If we can't connect to the 
DB</exception> 
</member> 
<member name="M:UserSecurity.User.ChangePassword(System.String,System.String)"> 
<summary>Changes the password for the currently logged in user, provided that the oldPassword
 matches with the current username.</summary> 
<param name="oldPassword">The password currently associated with the 
account.</param> 
<param name="newPassword">The password to associate with the account from now 
on.</param> 
<permission cref="T:System.Security.PermissionSet">public</permission> 
</member> 
<member name="P:UserSecurity.User.Username"> 
<value>Username accesses the internal username data member.</value> 
</member> 
</members> 
</doc>

Wir wollen nun gemeinsam die von VS.NET erzeugte XML durchgehen. Das doc-Tag stellt die einzige übergeordnete Ebene bereit, die ein beliebiges XML-Dokument erfordert. Innerhalb des assembly-Elements gibt der name-Knoten den Namen des Projekts an. Das members-Element wrappt alle Typen, Membervariablen, Eigenschaften und Methoden des Projekts. Im jeweiligen member-Knoten befindet sich die gesamte XML der eingegebenen Kommentare. Mit dem Attribut name des Memberknotens sollten wir uns allerdings einmal näher befassen. Der erste Buchstabe des Attributs gibt den Typ des Members an. Die möglichen Werte und deren Bedeutung sind im Folgenden aufgeführt.

  • T - Typ (Klassen)

  • F - Feld (Membervariablen)

  • P - Property (Eigenschaft) (Get/Set-Accessors)

  • M - Methode (Funktionen)

  • E - Ereignis

  • I - Unbekannt

Auf dieses Präfix folgen jeweils ein Doppelpunkt und der Name der Assembly. Was danach kommt, hängt vom Typ des Members ab. Bei Typen folgt auf den Namen der Assembly der Typ- oder Klassenname. Felder umfassen den Klassennamen und den Namen der Membervariablen. Bei Methoden und Eigenschaften folgt auf den Klassennamen der Funktionsname einschließlich der Typen beliebiger Parameter.
Innerhalb des Memberknotens finden Sie den gesamten Inhalt des Kommentars für dieses Member, einschließlich "summary", "param" und "returns".

Diese einfache XML-Datei enthält sämtliche Informationen, die für die Dokumentation des Objekts benötigt werden. Sie ist klar, prägnant und einfach. Es wird nur noch etwas XSL benötigt, um sie in eine dynamische, HTML-basierte Hilfesite zu verwandeln.

Generieren der Dokumentation

Lassen Sie uns nun einmal überlegen, was für die Dokumentation von Nutzen wäre. Auf der Hauptseite des Projekts sollten alle im Projekt verwendeten Typen aufgeführt werden. Der Typ sollte jeweils einen Link zu einer Liste der Member für diesen Typ enthalten. Jedes Member - ungeachtet ob Variable, Eigenschaft oder Funktion - sollte einen Link zu den Details zu diesem Member umfassen.

ASP.NET-Projekt, Teil 1

Erstellen Sie im ersten Schritt in Visual Studio.NET ein neues Projekt. Wählen Sie C# Projects und dann ASP.NET Web Application. Ich habe mein Projekt GenerateDoc genannt.
Als erstes erstellen Sie nun die ASP.NET-Seite, die die XML mithilfe unserer XSL-Dateien in HTML umwandelt. Indem Sie diese Seite zuerst gestalten, können Sie den XSL-Code testen, während Sie ihn schreiben. Benennen Sie die Seite WebForm1.aspx in GenerateDoc.aspx um. Zeigen Sie die zugrunde liegende Codeseite GenerateDoc.aspx.cs an und ändern Sie den Klassennamen in GenerateDoc. Fügen Sie am Anfang der Datei die folgenden Zeilen hinzu.

using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Xsl;

Fügen Sie in der Render-Methode den folgenden Code hinzu.

Vergewissern Sie sich, dass Sie die richtigen Pfade für die XML-Kommentardateien eingegeben haben. Kompilieren Sie das Projekt.

// Load the XML doc containing the comments
XmlDocument xmlCommentDoc = new XmlDocument();
xmlCommentDoc.Load("C:\\Inetpub\\wwwroot\\GenerateDoc\\UserDoc.xml");
// Load the XSL file containing the transformations
XslTransform xslCommentToDoc = new XslTransform();
xslCommentToDoc.Load("C:\\Inetpub\\wwwroot\\GenerateDoc\\GenerateDoc.xsl");
// Create StringBuilder and TextWriter to be used during transform
StringBuilder strDocOutput = new System.Text.StringBuilder();
TextWriter txtDocOutput = (System.IO.TextWriter)new System.IO.StringWriter(strDocOutput);
// GO!
xslCommentToDoc.Transform(xmlCommentDoc, null, txtDocOutput);
// Write out the results
Response.Write(twWriteOutput.ToString());

Dokumentieren des Projekts

Erstellen Sie nun die Datei GenerateDoc.xsl, um damit die Hauptprojektseite anzulegen. Beginnen Sie mit dem Einrichten des HTML-Textkörpers:

<xsl:template match="doc">
      <html>
            <head>
                  <title>GenerateDoc</title>
            </head>
            <body>
                  <xsl:apply-templates select="./assembly" />
            </body>
      </html>
</xsl:template>

Wenn Sie zum assembly-Knoten gelangen, geben Sie das Attribut name als den Projektnamen aus:

<xsl:template match="assembly">
<H1 style="font-family: arial, sans-serif; background-color: darkblue; color: white">
            Project:
            <xsl:value-of select="./name" />
      </H1>
      <xsl:apply-templates select="../members/member[starts-with(@name,'T:')]" />
</xsl:template>

Unsere raffinierte select-Anweisung sucht nach allen Memberknoten, deren Attribut name mit T: beginnt, das heißt nach allen Typen. Sie formatieren die Typen mit einem Link zur Memberliste der Klasse. Sie lesen den Namen des Typs aus, indem Sie die Zeichenfolge nach dem Punkt abrufen:

<xsl:template match="member[starts-with(@name,'T:')]">
      <A>
<xsl:attribute name="href">GenerateDoc.aspx?Type=<xsl:value-of 
select="@name" /></xsl:attribute>
            <H2 style="font-family: arial, sans-serif; color: 
darkblue"><xsl:value-of select="substring-after(@name,'.')" /></H2>
      </A>
      <xsl:apply-templates select="remarks" />
</xsl:template>

Für die Anmerkungen gestalten Sie eine Tabelle, damit Sie einen Einzug durchführen und den Hintergrund grau formatieren können:

<xsl:template match="remarks">
      <TABLE border="0" width="400">
            <TR>
                  <TD width="25"></TD>
                  <TD bgcolor="darkgray">
                        <span style="font-family: arial, sans-serif; background-color: 
darkgray;"><xsl:value-of select="." /></span>
                  </TD>
            </TR>
      </TABLE>
</xsl:template>

Führen Sie das Projekt nun aus. Starten Sie einen Browser und öffnen Sie https://localhost/GenerateDoc/GenerateDoc.aspx. Die Ausgabe sollte ähnlich der folgenden aussehen:

Bild02

ASP.NET-Projekt, Teil 2

Zur Unterstützung der Klassendetailseite und einer Memberdetailseite nehmen Sie ein paar Änderungen an der Seite GenerateDoc.aspx.cs vor. Anschließend generieren Sie zwei neue XSL-Dateien. Die Änderungen an GenerateDoc.aspx.cs ermöglichen es, den Wert des Type-Abfragezeichenfolgen-Parameters zu prüfen. Dann können Sie ermitteln, welche XSL-Datei geladen werden sollte. GenerateDoc.aspx.cs sollte wie folgt wiedergegeben werden.

String strType;
      String strXSLPath;
      strXSLPath = "C:\\Inetpub\\wwwroot\\GenerateDoc\\GenerateDoc.xsl";
      // Get the Type value from the query string
      strType = Request.Params.Get("Type");
      if (strType == null)
      {
            // Path already set above
      }
      // If Type begins with a "T", for types (classes)
      else if (strType.StartsWith("T"))
      {
            strXSLPath = "C:\\Inetpub\\wwwroot\\GenerateDoc\\GenerateType.xsl";
      }
      // If Type begins with a "M", for members
      else if (strType.StartsWith("M"))
      {
            strXSLPath = "C:\\Inetpub\\wwwroot\\GenerateDoc\\GenerateMember.xsl";
      }
      // Load the XML doc containing the comments
      XmlDocument xmlCommentDoc = new XmlDocument();
      xmlCommentDoc.Load("C:\\Inetpub\\wwwroot\\GenerateDoc\\UserDoc.xml");
      // Load the XSL file containing the transformations
      XslTransform xslCommentToDoc = new XslTransform();
      xslCommentToDoc.Load(strXSLPath);
      // Create StringBuilder and TextWriter to be used during transform
      StringBuilder strDocOutput = new System.Text.StringBuilder();
      TextWriter txtDocOutput = (System.IO.TextWriter)new System.IO.StringWriter(strDocOutput);
      // GO!
      xslCommentToDoc.Transform(xmlCommentDoc, null, txtDocOutput);
      // Write out the results
      Response.Write(txtDocOutput.ToString());

Dokumentieren des Typs

Die XSL-Datei GenerateType.xsl verwendet den Type-Parameter, um die in der XSL-Datei angeforderte Klasse zu finden. Anschließend werden alle Member dieses Typs herausgeschrieben. Dies geschieht anhand einer ausgeklügelten Zeichenfolgenmanipulation, um die einfachen Namen der Member auszulesen. Die Membernamen als solche sind Links zu den Details zu jedem Member.
Um XSL nun mitzuteilen, dass ein Parameter erwartet wird, muss dieser deklariert werden:

<xsl:param name="Type" />

Sie verwenden den Parameter, um den Memberknoten für den gewünschten Typ und um die Memberknoten für die Member dieses Typs auszuwählen.

<xsl:template match="doc">
      <html>
            <head>
                  <title>GenerateType</title>
            </head>
            <body style="font-family: arial, sans-serif;">
                  <xsl:apply-templates select="./assembly" />
                  <xsl:apply-templates select="//members/member[contains(@name,$Type)]" mode="type" />
                  <xsl:apply-templates select="//members/member[contains(@name,substring-
after($Type, 'T:'))]" mode="member" />
            </body>
      </html>
</xsl:template>

Der Membername als solcher ist ein Link zu noch detaillierteren Informationen zu diesem speziellen Member. Wir bereiten einen weiteren Abfragezeichenfolgen-Parameter vor, der an GenerateMember.xsl übergeben werden soll. Wir ermitteln, ob es sich bei dem Member um eine Methode, ein Feld, eine Eigenschaft oder ein Ereignis handelt, indem wir das Präfix prüfen. Anschließend können diese Informationen auf die Seite herausgeschrieben werden.

<xsl:template match="member" mode="member">
      <H3>
            <A><xsl:attribute name="href">GenerateDoc.aspx?Type=
<xsl:value-of select="@name" /></xsl:attribute><xsl:value-of select="
substring-after(substring-after(@name, substring-after($Type, 'T:')), '.')" /></A>
      </H3>
      <I>
            <xsl:choose>
                  <xsl:when test="starts-with(@name,'M:')">
                        Method:
                  </xsl:when>
                  <xsl:when test="starts-with(@name,'F:')">
                        Field:
                  </xsl:when>
                  <xsl:when test="starts-with(@name,'P:')">
                        Property:
                  </xsl:when>
                  <xsl:when test="starts-with(@name,'E:')">
                        Event:
                  </xsl:when>
            </xsl:choose>
      </I>
            <xsl:apply-templates select="summary"/>
</xsl:template>

Mit etwas XSL zum Herausschreiben des Typennamens und von summary sowie remarks erhalten wir eine Seite, die einen einzelnen Typ beschreibt. Die Ausgabe sollte wie folgt aussehen:

Bild03

Dokumentieren des Members

GenerateMember.xsl wird ausgeführt, wenn auf einen Membernamen geklickt wird. Es wird der gleiche Type-Parameter wie bei GenerateType.xsl verwendet und über GenerateDoc.aspx.cs sind keine weiteren Änderungen mehr erforderlich. Die XSL ist mit der in den beiden vorherigen Dateien vergleichbar. Es wird jedoch hiermit Unterstützung für Beispiele sowie Code, Ausnahmebedingungen, Rückgabetyp und Parameter bereitgestellt. Die Ausgabe sollte wie folgt aussehen:

Bild04

Inlinehilfe

Bis jetzt ist das doch alles schon recht ansehnlich, oder? Aber warten Sie, es geht weiter! Wenn Sie nun auf einen Typ oder ein Member verweisen, den bzw. das Sie vorher kommentiert haben, wird zudem auch dieses schicke QuickInfo-Popup angezeigt, das Sie bei allen integrierten Typen erhalten. Wenn Visual Studio feststellt, dass Sie eine bereits bekannte Funktion aufrufen, erscheint ein gelbes Popupfenster mit einer Definition der Funktion. Dieses QuickInfo enthält die summary-Kommentare der Funktion zusammen mit Kommentaren zu jedem Parameter. Dies ist eine wertvolle Hilfe, um dem Entwickler die Details einer Funktion wieder ins Gedächtnis zu rufen. Weder die Hilfe-Funktion muss aufgerufen werden, noch die Funktionsquelle geprüft werden. Hier beispielsweise das QuickInfo, das beim Programmieren eines Aufrufs meiner User.Login-Funktion zu Beginn angezeigt wurde.

Bild05

Sie haben nun nicht nur die Dokumentation für Ihr Projekt erstellt, sondern Sie haben auch die weitere Programmierung mit den gleichen Techniken, die Microsoft für alle .NET-Typen verwendet, wesentlich vereinfacht!

Verbessern der Lösung

Mit diesem Framework könnte das Projekt nun noch weiter verbessert werden, so dass auch XML-Kommentardateien von mehreren Projekten unterstützt werden. So könnte sogar eine gesamte Verzeichnisstruktur nach allen Kommentardateien durchsucht werden, um eine umfassende Dokumentationssammlung für die gesamte Anwendung zusammenzustellen. Oder alle XML-Kommentardateien könnten mit einem automatisierten Erstellungsprozess an eine zentrale Position kopiert bzw. sogar zu einer großen Kommentardatei zusammengefasst werden. Bei eher beständigen Projekten, die bereits abgeschlossen sind, könnte ein einfaches Programm, das mit sehr ähnlichen Techniken wie den in diesem Artikel vorgestellten arbeitet, statische HTML-Dokumentdateien entwickeln, anstatt die Ausgabe dynamisch auf Anforderung zu erzeugen.

Verwenden der Beispiele

Der Quellcode zu diesem Artikel enthält zwei Projekte. GenerateDoc.zip enthält das ASP.NET-Projekt und die XSL-Dateien, die die XML-Kommentare in eine Dokumentationssite umwandeln. Extrahieren Sie dieses Projekt in Ihr wwwroot-Verzeichnis (in der Regel C:\Inetpub\wwwroot). Legen Sie im Internetdienste-Manager ein virtuelles Verzeichnis an, das auf das von der ZIP-Datei erzeugte Verzeichnis GenerateDoc verweist (wahrscheinlich C:\Inetpub\wwwroot\GenerateDoc). Rufen Sie im Browser https://localhost/GenerateDoc/GenerateDoc.aspx auf, um die erstellte Dokumentation anzuzeigen.

User.zip umfasst das Projekt, das die XML-Kommentare enthält, die die Eingabe für GenerateDoc bereitstellen. Extrahieren Sie diese Datei in einem beliebigen Verzeichnis, und öffnen Sie User.csproj.Class1 enthält die Kommentare. UserDoc.xml ist die Ausgabedatei mit den XML-Kommentaren.

Zusammenfassung

Fügen Sie der Liste der Vorteile von .NET noch "macht die Dokumentationserstellung zu einem Kinderspiel" hinzu. Mit nur geringem Aufwand können Sie Ihren Programmiererkolleginnen und ?kollegen zukünftig das Leben erleichtern und im Handumdrehen den Dokumentationsbedarf Ihres nächsten Projekts erfüllen.