Zona HTML Zona Java Zona PHP Zona ASP Zona Bases de datos
Inicio > Tutoriales > Lenguajes orientados a objeto > C# > El lenguaje de programación C#
-Tutoriales

El lenguaje de programación C#


Tema 19: Documentación XML

. Concepto y utilidad de la documentación XML

La documentación de los tipos de datos creados siempre ha sido una de las tareas más pesadas y aburridas a las que un programador se ha tenido que enfrentar durante un proyecto, lo que ha hecho que muchas veces se escriba de manera descuidada y poco concisa o que incluso que no se escriba en absoluto. Sin embargo, escribirla es una tarea muy importante sobre todo en un enfoque de programación orientada a componentes en tanto que los componentes desarrollados muchas veces van a reutilizados por otros. E incluso para el propio creador del componente puede resultar de inestimable ayuda si en el futuro tiene que modificarlo o usarlo y no recuerda exáctamente cómo lo implementó.

Para facilitar la pesada tarea de escribir la documentación, el compilador de C# es capaz de generarla automáticamente a partir de los comentarios que el progamador escriba en los ficheros de código fuente.

El hecho de que la documentación se genere a partir de los fuentes permite evitar que se tenga que trabajar con dos tipos de documentos por separado (fuentes y documentación) que deban actualizarse simultáneamente para evitar incosistencias entre ellos derivadas de que evolucionen de manera separada ya sea por pereza o por error.

El compilador genera la documentación en XML con la idea de que sea fácilmente legible para cualquier aplicación. Para facilitar su legibilidad a humanos bastaría añaderle una hoja de estilo XSL o usar alguna aplicación específica encargada de leerla y mostrarla de una forma más cómoda para humanos.

Aunque explicar XML y XSL queda fuera del alcance del libro, en este tema se resumirán brevemente tanto XML como la forma de aplicar hojas XSL a ficheros XML.

. Introducción a XML

Antes de continuar es necesario hacer una pequeña introducción a XML ya que que es el lenguaje en que se han de escribir los comentarios especiales de documentación. Si ya conoce este lenguaje puede saltarse este epígrafe.

XML (Extensible Markup Language) es un metalenguaje de etiquetas, lo que significa que es un lenguaje que se utiliza para definir lenguajes de etiquetas. A cada lenguaje creado con XML se le denomina vocabulario XML, y la documentación generada por el compilador de C# está escrita en un vocabulario de este tipo.

Los comentarios a partir de los que el compilador generará la documentación han de escribirse en XML, por lo que han de respetar las siguientes reglas comunes a todo documento XML bien formado:

  • La información ha de incluirse dentro de etiquetas, que son estructuras de la forma:
    <<etiqueta>> <contenido> </<etiqueta>

    En <etiqueta> se indica cuál es el nombre de la etiqueta a usar. Por ejemplo:

    <EtiquetaEjemplo> Esto es una etiqueta de ejemplo </EtiquetaEjemplo>

    Como <contenido> de una etiqueta puede incluirse tanto texto plano (es el caso del ejemplo) como otras etiquetas. Lo que es importante es que toda etiqueta cuyo uso comience dentro de otra también ha de terminar dentro de ella. O sea, no es válido:

    <Etiqueta1> <Etiqueta2> </Etiqueta1></Eetiqueta2>

    Pero lo que sí sería válido es:

    <Etiqueta1> <Etiqueta2> </Etiqueta2></Etiqueta1>

    También es posible mezclar texto y otras etiquetas en <contenido>. Por ejemplo:

    <Etiqueta1> Hola <Etiqueta2> a </Etiqueta2> todos </Etiqueta1>
  • XML es un lenguaje sensible a mayúsculas, por lo que si una etiqueta se abre con una cierta capitalización, a la hora de cerrarla habrá que usar exactamente la misma.
  • Es posible usar la siguiente sintaxis abreviada para escribir etiquetas sin <contenido>:
    <<etiqueta>/>

    Por ejemplo:

    <<EtiquetaSinContenidoDeEjemplo>/>
  • En realidad en la <etiqueta> inicial no tiene porqué indicarse sólo un identificador que sirva de nombre para la etiqueta usada, sino que también pueden indicarse atributos que permitan configurar su significado. Estos atributos se escriben de la forma <nombreAtributo> = "<valor>" y separados mediante espacios. Por ejemplo:
    <EtiquetaConAtributo AtributoEjemplo="valor1" >
        Etiqueta de ejemplo que incluye un atributo
    </EtiquetaConAtributo>
    
    <EtiquetaSinContenidoYConAtributo AtributoEjemplo="valor2" />
  • Sólo puede utilizarse caracteres ASCII, y los caracteres no ASCII (acentos, eñes, ...) o caracteres con algún significado especial en XML han de ser sustituidos por secuencias de escape de la forma &#<códigoUnicode>;. Para los caracteres más habituales también se han definido las siguientes secuencias de escape especiales:
Carácter Secuencia de escape Unicode Secuencia de escape especial
< &#60; &lt;
> &#62; &gt;
& &#38; &amp;
' &#39; &apos;
" &#34; &quot;

Tabla 11: Secuencias de espace XML de uso frecuente

. Comentarios de documentación XML

. Sintaxis general

Los comentarios de documentación XML se escriben como comentarios normales de una línea pero con las peculiaridades de que su primer carácter ha de ser siempre / y de que su contenido ha de estar escrito en XML ya que será insertado por el compilador en el fichero XML de documentación que genera. Por tanto, son comentarios de la forma:

/// <textoXML>

Estos comentarios han preceder las definiciones de los elementos a documentar. Estos elementos sólo pueden ser definiciones de miembros, ya sean tipos de datos (que son miembros de espacios de nombres) o miembros de tipos datos, y han de colocarse incluso incluso antes que sus atributos.

En <textoXML> el programador puede incluir cualesquiera etiquetas con el significado, contenido y atributos que considere oportunos, ya que en principio el compilador no las procesa sino que las incluye tal cual en la documentación que genera dejándo en manos de las herramientas encargadas de procesar dicha documentación la determinación de si se han usado correctamente.

Sin embargo, el compilador comprueba que los comentarios de documentación se coloquen donde deberían y que contegan XML bien formado. Si no fuese así generaría un mensaje de aviso y en la documentación generada los sustituiría por un comentario XML que explicase el tipo de error cometido.

. El atributo cref

Aunque en principio los atributos de las etiquetas no tienen ningún significado predeterminado para el compilador, hay una excepción: el atributo cref siempre va a tener un significado concreto consistente en forzarlo a comprobar cuando vaya a generar la documentación si existe el elemento cuyo nombre indique y, si no es así, hacerle producir un mensaje de aviso (su nombre viene de "check reference")

Los elementos especificados en cref suelen indicarse mediante calificación completa, y pueden ser tanto nombres de miembros como de espacios de nombres. En el Tema 6: Espacios de Nombres ya se explicó como indicar así nombres de tipos y de espacios de nombres, mientras que para indicar el de miembros de tipos basta escribir el nombre completo del tipo donde estén definidos seguido de un punto tras el cual, dependiendo del tipo de miembro del que se trate, se escribiría :

  • Si es un campo, propiedad, evento o tipo interno, su nombre.
  • Si es un método, su nombre seguido de los nombres completos de los tipos de sus parámetros separados mediante comas y entre paréntesis. Estos nombres de tipos de parámetros llevan un carácter @ concatendo al final en los parámetros ref u out, un carácter * al final en los que sean de tipos punteros, un símbolo [] por cada nivel de anidación al final de los que sean tablas unidimensionales, y una estructura de la forma [0:,0:] al final de los que sean tablas bidimensionales (para tablas de más dimensiones simplemente se irían añadiendo los bloques ,0: apropiados).
  • Si es un indizador, el identificador Item seguido de la lista de tipos de sus índices como si de los parámetros de un método se tratase
  • Si es un constructor de objeto, el identificador #ctor seguido de la lista de tipos de sus parámetros como si de un método normal se tratase. Si el constructor fuese de tipos entonces el identificador usado sería #cctor
  • Si es un destructor, el identificador Finalize.
  • Si es un operador, el identificador que represente a ese operador segudio de la lista de los tipos de sus operandos como si fuesen los parámetros de un método normal. En la Tabla 12 se resumen los identificador que se dan a cada operador:
Operador Identificador
+ op_Addition
- op_Substraction
* op_Multiply
/ op_Division
% op_Modulus
< op_LessThan
> op_GreaterThan
>= op_GreaterThanOrEqual
<= op_LowerThanOrEqual
== op_Equality
!= op_Inequality
! op_LogicalNot
Operador Identificador
& op_BitwiseAnd
| op_BitwiseOr
^ op_ExclusiveOr
~ op_OnesComplement
<< op_LeftShift
>> op_RightShift
true op_True
false op_False
++ op_Increment
-- op_Decrement
Conversión explícita Op_Explict
Conversión implícita Op_Implicit

Tabla 12: Nombres dados a operadores en documentación XML

En el caso de los operadores de conversión, tras la lista de parámetros se incluye adicionalmente un carácter ~ seguido del tipo de retorno del operador.

Para que se entienda mejor la forma en que se han de dar valores a cref, a continuación se muestra un fragmento de código de ejemplo en el que junto a cada definición se ha escrito un comentario con el valor que habría que darle a cref para referenciarla:

// cref="Espacio"
namespace Espacio
{
  // cref="Espacio.Clase"
  class Clase
  {
    // cref="Espacio.Clase.Campo"
    int Campo;
    
    // cref="Espacio.Clase.Propiedad"
    int Propiedad
    { set {} }
    
    // cref="Espacio.Clase.EstructuraInterna"
    struct EstructuraInterna
    {}
    
    // cref="Espacio.Clase.DelegadoInterno"
    public delegate int DelegadoInterno(string s, float f);
    
    // cref ="Espacio.Clase.Evento"
    public event DelegadoInterno Evento;
    
    // cref="Espacio.Clase.Metodo(System.Int32, System.Int32@,
    //       System.Int32*, System.Int32@,
    //       System.Int32[][], System.Int32[0:, 0:, 0:])"
    int Metodo(int a,  out int b, int * c, ref d, int[][] e, int[,,] f)
    {return 1;}
    
    // cref="Espacio.Clase.Item(System.String)"
    int this[string s]
    { set {} }
    
    // cref="Espacio.Clase.#ctor"
    Clase(int a)
    {}
    
    // cref="Espacio.Clase.#cctor"
    static Clase(int a)
    {}
    
    // cref="Espacio.Clase.Finalize"
    ~X()
    {}
    
    // cref="Espacio.Clase.op_Addition(Espacio.Clase, Espacio.Clase)"
    public static int operator +(Clase operando1, Clase operando2)
    { return 1; }
    
    // cref="Espacio.Clase.op_Explicit (Espacio.Clase)~System.Int32"
    public static explicit operator int(Clase fuente)
    { return 1; }
  }
}

En realidad no es siempre necesario usar calificación completa en el valor de cref. Si se referencia a un tipo desde la misma definición de espacio de nombres desde donde se le definió o que importa su espacio de nombres, no es necesario incluir dicho espacio en la referencia; y si se referencia a un miembro desde el el mismo tipo donde se definió, no es necesario incluir ni el nombre del tipo ni el de su espacio de nombres.

. Etiquetas recomendadas para documentación XML

Aunque el programador puede utilizar las etiquetas estime oportunas en sus comentarios de documentación y darles el significado que quiera, Microsoft recomienda usar un juego de etiquetas concreto con significados concretos para escribir ciertos tipos de información común. Con ello se obtendría un conjunto básico de etiquetas que cualquier herramienta que trabaje con documentación XML pueda estar preparada para procesar (como veremos más adelante, el propio Visual Studio.NET da ciertos usos específicos a la información así documentada)

En los siguientes epígrafes se explican estas etiquetas recomendadas agrupándolas según su utilidad. Todas son opcionales, y no incluirlas sólo tiene el efecto de que no en la documentación resultante no se generarían las secciones correspondientes a ellas.

. Etiquetas de uso genérico

Hay una serie de etiquetas predefinidas que pueden colocarse, en cualquier orden, precediendo las definiciones de miembros en los ficheros fuente. Estas etiquetas, junto al significado recomendado para su contenido, son las explicadas a continuación:

  • <summary>: Su contenido se utiliza para indicar un resumen sobre el significado del elemento al que precede. Cada vez que en VS.NET se use el operador . para acceder a algún miembro de un objeto o tipo se usará esta información para mostrar sobre la pantalla del editor de texto un resumen acerca de su utilidad.
  • <remarks>: Su contenido indica una explicación detallada sobre el elemento al que precede. Se recomienda usar <remarks> para dar una explicación detallada de los tipos de datos y <summary> para dar una resumida de cada uno de sus miembros.
  • <example>: Su contenido es un ejemplo sobre cómo usar el elemento al que precede.
  • <seealso>: Se usa para indicar un elemento cuya documentación guarda alguna relación con la del elemento al que precede. No tiene contenido y el nombre del elemento al que se remite se indicá en su atributo cref, por lo que el compilador comprobará si existe. Para indicar múltiples documentaciones relativas a un cierto elemento basta usar una etiqueta <seealso> por cada una.
  • <permission>: Se utiliza para indicar qué permiso necesita un elemento para poder funcionar. En su contenido se indica una descripción del mismo, y su atributo cref suele usarse para indicar el tipo que representa a ese permiso Por ejemplo:
    /// <permission cref="System.Security.Permissions.FileIOPermission">
    ///     Necesita permiso de lectura/escritura en  el directorio C:\Datos
    /// </permission>

    Como con <seealso>, si un miembro ha de disponer varios tipos de permisos puede documentarse su definición con tantas etiquetas <permission> como sea necesario.

. Etiquetas relativas a métodos

Además de las etiquetas uso general ya vistas, en las definiciones de métodos se pueden usar las siguientes etiquetas recomendadas adicionales para describir sus parámetros y valor de retorno:

  • <param>: Permite documentar el significado de un parámetro de un método. En su propiedad name se indica el nombre del parámetro a documentar y en su contenido se describe su utilidad. Por ejemplo:
    /// <summary> Método que muestra un texto por pantalla </summary>
    /// <param name="texto">  Texto a mostrar  </param>
    
    bool MuestraTexto(string texto)
    {...}

    Al generarse la documentación se comprueba si el método documentado dispone de algún parámetro con el nombre indicado en name y, como ocurre con cref, si no fuese así se generaría un mensaje de aviso informando de ello.

  • <paramref>: Se usa para referenciar a parámetros de métodos. No tiene contenido y el nombre del parámetro referenciado se indica en su atributo name. Por ejemplo:
    /// <summary>
    ///     Método que muestra por pantalla un texto con un determinado color
    /// </summary>
    /// <param name="texto">  Texto a mostrar </param>
    /// <param  name="color">
    ///     Color con el que mostrar el <paramref name="texto"/> indicado
    /// </param>
    
    bool MuestraTexto(string texto, Color color)
    {...}

    Nuevamente, al generarse la documentación se comprobará si realmente el parámetro referenciado existe en la definición del método documentado y si no es así se generá un mensaje de aviso informando de ello.

  • <returns>: Permite documentar el significado del valor de retorno de un método, indicando como contenido suyo una descripción sobre el mismo. Por ejemplo:
    /// <summary>
    ///     Método que muestra por pantalla un texto con un determinado color
    /// </summary>
    /// <param name="texto">  Texto a mostrar </param>
    /// <param  name="color">
    ///     Color con el que mostrar el <paramref name="texto"/> indicado
    /// </param>
    /// <returns> Indica si el método se ha ejecutado con éxito o no </summary>
    
    bool MuestraTexto(string texto, Color color)
    {...}

. Etiquetas relativas a propiedades

El uso más habitual de una propiedad consiste en controlar la forma en que se accede a un campo privado, por lo que esta se comporta como si almacenase un valor. Mediante el contenido de la etiqueta <value> es posible describir el significado de ese valor:

private int edad;
/// <summary>
///     Almacena la edad de una persona. Si se le asigna una edad menor
///     que 0 la sustituye por 0.
/// </summary>
/// <value> Edad de la persona representada </value>
public int Edad
{
  set { edad  = (value<0)? 0:value }
  get { return edad; }
}

. Etiquetas relativas a excepciones

Para documentar el significado de un tipo defindo como excepción puede incluirse un resumen sobre el mismo como contenido de una etiqueta de documentación <exception> que preceda a su definición. El atributo cref de ésta suele usarse para indicar la clase de la que deriva la excepción definida. Por ejemplo:

/// <exception cref="System.Exception">
///        Excepción de ejemplo creada por Josan
/// </exception>

class JosanExcepción: Exception
{}

. Etiquetas relativas a formato

Para mejorar la forma de expresar el contenido de las etiquetas de documentación que se utilicen es posible incluir en ellas las siguientes etiquetas de formato:

  • <see>:Se utiliza para indicar hipervínculos a otros elementos de la documentación generada. Es una etiqueta sin contenido en la que el destino del enlace es la documentación del miembro cuyo nombre completo se indica en su atributo cref. Ese nombre es también el texto que las hojas de estilo sueln mostrar para representar por pantalla el enlace, por lo que los usos de esta etiqueta suelen ser de la forma:
    /// <summary>
    ///    Muestra por la salida estándar el mensaje ¡Hola!.
    ///    Si no sabe como se escribe en pantalla puede consultar la
    ///    documentación del método
    ///    <see cref="System.Console.WriteLine"/>.
    /// </summary>
    public static void Saluda()
    {
      Console.WriteLine("¡Hola!");
    }

    Nótese que la diferencia de <see> y <seealso> es que la primera se usa para indicar enlaces en medio de textos mientras que la otra se usa para indicar enlaces que se deseen incluir en una sección aparte tipo "Véase también".

  • <code> y <c>: Ambas etiquetas se usan para delimitar textos han de ser considerarse fragmentos de código fuente. La diferencia entre ellas es que <code> se recomienda usar para fragmentos multilínea y <c> para los de una única línea; y que las hojas de estilo mostrarán el contenido de las etiquetas <code> respetando su espaciado y el de las etiquetas <c> sin respetarlo y trantando cualquier aparición consecutiva de varios caracteres de espaciado como si fuesen un único espacio en blanco.

    En general, <code> suele usarse dentro de etiquetas <example> para mostrar fragmentos de códigos de ejemplo, mientras que <c> suele usarse para hacer referencia a elementos puntales de los códigos fuente. Por ejemplo:

    /// <example>
    ///    Este ejemplo muestra cómo llamar al método
    ///    <c>Cumple()</c> de esta clase:
    ///    <code>
    ///        Persona p = new Persona(...);
    ///        p.Cumple();
    ///    </code>
    /// </example>
  • <para>: Se usa para delimitar párrafos dentro del texto contenido en otras etiquetas, considerándose que el contenido de cada etiqueta <para> forma parte de un párrafo distinto. Generalmente se usa dentro de etiquetas <remarks>, ya que son las que suelen necesitar párrafos al tener un contenido más largo. Por ejemplo:
    /// <remarks>
    ///    <para>
    ///        Primer párrafo de la descripción del miembro...
    ///    </para>
    ///    <para>
    ///        Segundo párrafo de la descripción del miembro...
    ///    </para>
    /// </remarks>
  • <list>: Se utiliza para incluir listas y tablas como contenido de otras etiquetas. Todo uso de esta etiqueta debería incluir un atributo type que indique el tipo de estructura se desea definir según tome uno de los siguientes valores:
    • bullet: Indica que se trata de una lista no numerada
    • number: Indica que se trata de una lista numerada
    • table: Indica que se trata de una tabla

    El contenido de <list> dependerá del tipo de estructura representado en cada caso:

    • Si se trata de una lista normal -ya sea numerada o no numerada- su contenido será una etiqueta <item> por cada elemento de la lista, y cada etiqueta de este tipo contendrá una etiqueta <description> con el texto correspondiente a ese elemento. Por ejemplo:
      /// <list type="bullet">
      ///         <item>
      ///                    <description>
      ///                               Elemento 1
      ///                    </description>
      ///         </item>
      ///         <item>
      ///                    <description>
      ///                               Elemento 2
      ///                    </description>
      ///         </item>
      /// </list>
    • Si tratase de una tabla, su contenido sería similar al de las listas normales sólo que por cada fila se incluiría una etiqueta <item> y dentro de ésta se incliría una etiqueta <description> por cada columna de esa fila.

      Además, opcionalmente se podría incluir una etiqueta <listheader> antes de las etiquetas <item> donde se indicaría cuál ha de ser el texto de la cabecera de la tabla. Esta etiqueta se usa igual que las etiquetas <item>: incluirá una etiqueta <description> por cada columna.

    • Por último, si fuese una lista de definiciones cada <item> contendría una primera etiqueta <term> con el nombre del elemento a definir y otra segunda etiqueta <description> con su definición. Opcionalmente también podria incluirse una etiqueta <listheader> con la cabecera de la lista. Por ejemplo:
      /// <list type="bullet">
      ///         <item>
      ///                    <term>
      ///                               Término 1
      ///                    </term>
      ///                    <description>
      ///                               Descripción de término 1
      ///                    </description>
      ///         </item>
      ///         <item>
      ///                    <term>
      ///                               Término 2
      ///                    </term>
      ///                    <description>
      ///                               Descripción de término 2
      ///                    </description>
      ///         </item>
      /// </list>

. Generación de documentación XML

. Generación a través del compilador en línea de comandos

Usando el compilador en línea de comandos puede generarse documentación sobre los tipos definidos en los fuentes a compilar usando la opción de compilación /doc:<fichero>. Por ejemplo, para compilar un fichero de código fuente Persona.cs y generar su documentación en Persona.xml, habría que llamar al compilador con:

csc persona.cs /doc:persona.xml

Si se abre con Internet Explorer el fichero XML así generado se verá un conjunto de etiquetas que recogen toda la información ubicada en los comentarios de documentación de los fuentes compilados. Aunque para una persona pueda resultar difícil leer esta información, para una aplicación hacerlo es muy sencillo a través de un analizador XML. Si se dese que también sea legible para humanos basta abrirlo con cualquier editor de textos y añadirle una primera línea de la forma:

<?xml:stylesheet href="<ficheroXSL>" type="text/xsl"?>

Con esta línea se indica que se desea utilizar el fichero indicado en <ficheroXSL> como hoja de estilo XSL con la que convertir la documentación XML a algún lenguaje más fácilmente legible por humanos (generalmente, HTML). Por ejemplo, si doc.xsl es el nombre de dicho fichero XSL, bastaría escribir:

<?xml:stylesheet href="doc.xsl" type="text/xsl"?>

Para hacerse una idea de las diferencias existentes entre abrir con Internet Explorer un fichero de documentación sin hoja XSL asociada y abrir ese mismo fichero pero asociándole una hoja XSL, puede observar las siguientes ilustraciones:

Ilustración 6:  Documentación XML sin hoja de estilo
Ilustración 7:  Documentación  XML con hoja de estilo XSL

No se preocupe si no sabe escribir hojas de estilo, pues como se explica en el siguiente epígrafe, Visual Studio.NET incluye una herramienta que puede generar directamente la documentación en un HTML fácilmente legible para humanos.

. Generación a través de Visual Studio.NET

Si prefiere usar Visual Studio.NET, entonces para la generación de la documentación basta señalar el proyecto a documentar en el Solution Explorer y escribir el nombre del fichero XML a generar en el cuadro de texto View -> Property Pages -> Configuration Properties -> Build -> XML Documentation File

Cuando se compile el proyecto, la documentación XML sobre el mismo se guardará en el fichero indicado en el cuadro de texto anterior. Este fichero se almacenará dentro de la subcarpeta Bin del directorio del proyecto, y si se desea poder visualizarla desde el Solution Explorer hay que activar en éste el botón Show All Files.

En principio, para conseguir visualizar esta documentación en un formato más legible para humanos podría asociársele una hoja XSL como se explicó para el caso del compilador en línea de comandos. Sin embargo, Visual Studio.NET proporciona una forma más sencilla de hacerlo a través de la herramienta ubicada en Tools -> Build Comments Web Pages Esta utilidad a partir de la información incluida en las etiquetas recomendadas de los comentarios del fuente genera páginas HTML que muestran la documentación del proyecto de una forma vistosa e intuitiva (ver Ilustración)

Ilustración 8:  Documentación HTML generada por Visual Studio.NET

. Estructura de la documentación XML

Ahora que ya sabemos cómo escribir comentarios de documentación y generar a partir de ellos un fichero XML con la documentación de los tipos de datos de un fichero, sólo queda estudiar cuál es concretamente la estructura de dicho fichero generado ya que entenderla es fundamental para la escritura de aplicaciones encargadas de procesarlo.

En principio, si compilamos como módulo un fuente sin comentarios de documentación pero solicitando la generación de documentación, se obtendrá el siguiente fichero XML:

<?xml version="1.0"?>
<doc>
  <members>
  </members>
</doc>

Como se ve, la primera línea del fichero es la cabecera típica de todo fichero XML en la que se indica cuál es la versión del lenguaje que utiliza. Tras ella se coloca una etiqueta <doc> que contendrá toda la documentación generada, y los comentarios de documentación de los miembros del fuente compilado se irían incluyendo dentro de la etiqueta <members> que contiene (en este caso dicha etiqueta está vacía ya que el fuente compilado carecía de comentarios de documentación)

Si hubiésemos compilado el fuente como librería o como ejecutable se habría generado un ensamblado, y a la estructura anterior se le añadiría una etiqueta adicional dentro de <doc> con información sobre el mismo, quedando:

<?xml version="1.0"?>
<doc>
  <assembly>
    <name>Persona</name>
  </assembly>
  <members>
  </members>
</doc>

Como se ve, dentro de la etiqueta <assembly> contenida en <doc> se indican las características del ensamblado generado. En concreto, su nombre se indica en la etiqueta <name> que contiene (se supone que el ensamblado se compiló con el nombre Persona)

Si ahora le añadimos comentarios de documentación veremos que el contenido de estos se inserta dentro de la etiqueta <members>, en una etiqueta <member> específica para cada miembro con comentarios de documentación. Por ejemplo, dado el fuente:

/// <summary>
///         Clase de ejemplo de cómo escribir documentacion XML
/// </summary>
class A
{
  /// <summary>
  ///         Método principal de ejemplo perteneciente a clase <see cref="A"/>
  /// </summary>
  /// <remarks>
  ///         No hace nada
  /// </remarks>
  static void Main()
  {}
}

La documentación XML que generara compilarlo con la opción /doc es:

<?xml version="1.0"?>
<doc>
  <assembly>
    <name>A</name>
  </assembly>
  <members>
    <member name="T:A">
      <summary>
      Clase de ejemplo de cómo escribir documentacion XML
      </summary>
    </member>
    <member name="M:A.Main">
      <summary>
      Método principal de ejemplo perteneciente a clase <see cref="T:A"/>
      </summary>
      <remarks>
      No hace nada
      </remarks>
    </member>
  </members>
</doc>

Como puede verse, dentro de la etiqueta <members> no se sigue ninguna estructura jerárquica a la hora de describir los elementos del fuente, sino que todos se describen al mismo nivel y de la misma forma: se incluye una etiqueta <member> por cada miembro documentado en cuyo atributo name se indica su nombre y en cuyo contenido se inserta el texto de sus comentarios de documentación.

Nótese que a cada elemento se le da en el atributo name de su etiqueta <member> correspondiente un identificador que lo distingue unívocamente del resto de miembros documentados y que sigue la siguiente sintaxis:

<indicadorElemento>:<nombreCompletamenteCalificado>

El <indicadorElemento> es simplemente un carácter que indica qué tipo de elemento se documenta dentro de la etiqueta <member>. Puede tomar estos valores:

Indicador de tipo de elemento Tipo de elemento indicado
T Tipo de dato
F Campo
P Propiedad o indizador
M Método (incluidos operadores y contructores)
E Evento

Tabla 13: Indicadores de tipos de elementos en documentaciones XML

Como se ve en el ejemplo, en la documentación generada se usa también la sintaxis de los valores del atributo name de las etiquetas <member> para representar las referencias mediante atributos cref. Además, cuando dicha sintaxis se usa para expresar valores de cref pueden usarse dos tipos de indicadores más:

Indicador de tipo de elemento Tipo de elemento indicado
N Espacio de nombres
! Ninguno. Se genera cuando el miembro indicado en cref no existe.

Tabla 14: Indicadores de tipos de elementos para atributos cref

La idea que hay detrás de usar la sintaxis vista para representar elementos del fuente es proporcinar un mecanismo sencillo mediante el que las herramientas encargadas de procesar las documentaciones XML puedan determinar cuáles son los miembros documentados o referenciados y acceder, con ayuda de los tipos de System.Reflection, a sus metadatos asociados.

. Separación entre documentación XML y código fuente

A veces puede que interesar incrustar toda la documentación en el mismo fichero que el código fuente, por ejemplo si se desea reusarla en múltiples fuentes o si es muy voluminosa e incluirla en el fuente dificultaría su legibilidad. Para estos casos se da la posiblidad de dejar la documentación en un fichero XML aparte y referenciarla en el código fuente a través de la etiqueta de documentación <include>, que su usa así:

<include file="<nombreFichero>" path="<rutaDocumentación>"/>

Cuando el compilador encuentre esta etiqueta al generar la documentación lo que hará será tratarla como si fuese la etiqueta del fichero <nombreFichero> indicada por la expresión XPath <rutaDocumentación> Por ejemplo, si se tiene el código:

/// <include file="otro.xml" path="Miembros/Miembro[@nombre="A"]/*"/>
class A
{}

En este uso de <include> se está indicando que se ha de insertar todo el contenido de la etiqueta <Miembro> contenida en <Miembros> cuyo atributo nombre valga A. Luego, si el contenido del fichero otro.xml es de la forma:

<Miembros>
  ...
  <Miembro name="A">
    <remarks>
      Ejemplo de inclusión de documentación XML externa
    </remarks>
    <example>
      Para crear un objeto de esta clase usar:
        <code>
          A obj = new A();
        </code>
    </example>
  </Miembro>
  ...
</Miembros>

Entonces, el compilador generará documentación como si el fuente contuviese::

/// <remarks>
///         Ejemplo de inclusión de documentación XML externa
/// </remarks>
/// <example>
///         Para crear un objeto de esta clase usar:
///         <code>
///                    A obj = new A();
///         </code>
/// </example>
class A
{}
 
Patrocinados
 

Copyright © 1999-2006 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network