Documentación: Configuración

Dentro de una misma solución de Visual Studio podemos ver los comentarios sin problema, sin embargo cuando creamos una librería por ejemplo a través de NuGet también nos interesa que estos comentarios sean visibles para el consumidor de la librería, esto es posible gracias a unos ficheros XML que incluyen estos comentarios.

Estos ficheros XML no se generan de forma automática, para habilitarlos tenemos dos opciones, a través de la interfaz de Visual Studio o modificando el archivo del proyecto (.csproj).

SDK (archivo de proyecto)

La opción más segura es cambiando el fichero de proyecto usnado la etiqueta <GenerateDocumentationFile>, esto generará los ficheros XML en la ruta adecuada para el proceso de creación del paquete (dotnet pack, nuget pack,…)

<Project>
  <PropertyGroup>
    <!-- Allows to see coments in code -->
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
    <!-- Optional directory path, only if necessary -->
    <DocumentationFile>$(OutputPath)\$(AssemblyName).xml</DocumentationFile>
  </PropertyGroup>
</Project>

Esto puede ser hecho de forma global usando un fichero Directory.Build.props colocado en la raíz de la solución, por ejemplo añadiendo el contenido del ejemplo anterior todos los proyectos de la solución generarán la documentación.

<DocumentationFile> indica la ruta donde se colocarán los ficheros XML, pero como se ha comentado antes es mejor no usarla.

Visual Studio

En este caso usamos la interfaz, simplemente vamos a las propiedades del proyecto a la sección Build y marcamos XML documentation file, que equivale al tag <GenerateDocumentationFile> esto automaticamente rellenará el campo con una ruta por defecto que equivale al campo <DocumentationFile> .

Hay que tener en cuenta que esta configuración es para Debug así que para otras configuraciones habrá que hacer lo mismo.

También es recomendable habilitar los analizadores de código para que muestren avisos de todos los métodos públicos que tendrían que estar documentados.

Sandcastle

SandCastle es una herramienta desarrollada por Microsoft que genera documentación de forma automatizada en un formato similar al que podemos ver en la propia documentación de referencia oficial de Microsoft, Sandcastle se puede descargar desde: https://github.com/EWSoftware/SHFB

En la sección Build seleccionamos la versión de framework que vamos a usar y la carpeta donde guardaremos el log, es útil colocarlo en la misma carpeta que el archivo de proyecto pero no es necesario asociarlo al código fuente, hay que indicar en este caso Fixed Path para que no lo ubique en la ruta por defecto sino en la indicada.

Indicamos también en que formato queremos mostrar la documentación, según como queramos publicar la documentación elegiremos uno u otro (web, html help,…).

En el panel Project Explorer dentro de Documentation Sources sacamos el menú contextual y agregamos los archivos xml de documentación y los ensamblados que harán falta posteriormente para que Sandcastle pueda usar reflection de cara a generar por ejemplo la información de los namespaces que se verá más adelante.

Dentro de References podemos agregar otros proyectos o ensamblados a los que se haga referencia pero de los cuales no se quiera generar documentación.

Agregar otros proyectos

En la sección Help File es donde indicaremos información relativa al archivo de documentación.
Indicamos los campos Help Title que es el título para la documentación, el nombre del archivo generado en Help file name y el idioma en Help file language.
Podemos indicar campos opcionales como Feedback e-mail address para indicar quien es el autor de la documentación, así como un texto asociado a esta dirección en Feedback e-mail link text.


Información del archivo de documentación

En la sección Summaries vamos a indicar un texto para los namespaces ya que Visual Studio por defecto no permite comentarlos y Sandcastle genera mensajes de advertencia. Usando el botón Edit namespace summaries podemos seleccionar el namespace que queramos comentar junto con un texto asociado.

Documentación para namespaces

La documentación generada se ubicará en la carpeta help dentro de la carpeta que hayamos especificado.

En la salida (pestaña Build Output) se pueden ver los errores generados, habitualmente enlaces incorrectos.

Documentación: Configuración

Documentación: Referencia

Simplemente usando el comentario triple /// en la cabecera de una estructura de código (clase, método,…) automáticamente se generará la base del comentario, como dato adicional los namespaces no se pueden comentar.

Estos comentarios que generemos se guardarán en ficheros XML, por lo tanto al comentar hay que tener en cuenta que algunos caracteres pueden dar error, por ejemplo ‘<’ se convierte en < y ‘>’ se convierte en &gt;

También comentar que algunas de las etiquetas que se van a explicar pueden no mostrarse correctamente a través de IntelliSense pero si se verán correctamente en la documentación final.

Uso de enlaces

Cualquier etiqueta de documentación es susceptible de usar el atributo cref, este atributo tiene ciertas características para hacer referencia a otros elementos de código como se verá más adelante, por ejemplo para agregar una referencia a un tipo genérico usaríamos:

<see cref="Robot{T}" />

La lista a continuación son prefijos que se pueden agregar para especificar el tipo de código al que se hace referencia, si está bien referenciados no hace falta ya que el compilador lo agrega automáticamente, dependiendo del tipo de enlace se usará un prefijo u otro:

ClaveDescripción
N Namespace
T Tipo: clase, interfaz, estructura, enumerado, delegado
F Campo
P Propiedad
M Método (incluyendo constructores, operadores,…)
E Evento
¡ Cadena de error, generado por el compilador cuando hay un error

Por ejemplo, para un tipo se podría usar:

<see cref="nCubed.Core.Exceptions.SemanticException"/>

En caso de que se haga una referencia a código de .NET, para que Sandcastle lo encuentre correctamente se haría así:

<see cref="T:System.Func`1"/> to be processed.

También se puede usar para hacer referencia a un método de una interfaz genérica:

<see cref="nCubed.Core.Expressions.IAnyEnumerableCollection`1.Any"/>

Si hay dos parámetros genéricos se haría:

<see cref="nCubed.CQRS.Infrastructure.ProcessManagerRepository`2"/>

Cuando se hace referencia a métodos

<see cref="M:System.Object.Equals(System.Object)"/>

Referencia

A continuación la referencia de las etiquetas disponibles, todas las etiquetas se explican con la misma estructura:

  • Nombre de la etiqueta.
  • Descripción.
  • Ejemplo de sintaxis.
  • Imagen de ejemplo del resultado en documentación en línea creada con SandCastle (muy similar a MSDN) y en Visual Studio si aplica.

<summary>

Describe un tipo o miembro del mismo. Este texto es el único origen de información para IntelliSense, y se muestra también en Object Browser Window. Admite también el atributo cref. Es el elemento por defecto que aparece al empezar la documentación con ///

/// <summary>
/// Base constructor por person object.
/// </summary>

<c> <code>

El texto indicado representa código y se representará como tal, con el estilo de letra para código, si se usa <code> aparecerá encuadrado. Ejemplo:

/// <summary> 
/// Name used for <c>Person</c> object. 
/// It can be used as <code> Person p = new Person(); </code>
/// </summary> 

<example>

Crea un ejemplo para la documentación, si es para crear un ejemplo de código es recomendable usarlo junto con la etiqueta <code>.

/// <example>
/// It defines a SecondName for the user, 
/// it is used normally with <c>Name</c> as 
/// <code>string s = Name + SecondName;</code>
/// </example>

<exception>

Sirve para indicar que excepciones se lanzarán, se puede usar con métodos, propiedades, eventos e índices. Se puede usar el atributo cref que permite indicar una referencia a una excepción.

/// <exception cref="ArgumentNullException">
/// Returns error if <c>Name</c> is null.
/// </exception>

<include>

Permite incluir comentarios adicionales en otro archivo, esto es útil para poder usar varios ficheros a la vez y no incluir los comentarios directamente en código.

Se usan los siguientes atributos: file con el nombre del fichero adicional y path con la ruta XPath al comentario de código.

Al compilar el contenido el fichero referenciado se incrusta en la sección que hace la referencia como si se hubiera escrito directamente.

A través de XPath accedemos a la estructura xml que contiene la documentación propiamente dicha en el formato esperado. Un ejemplo de sintaxis es:

<include file='filename' path='tagpath[@name="id"]' />

Y si creamos un documento XML como:

<?xml version="1.0"?>
<CustomDoc>
    <CustomMember name="Animal">
	<summary>
		Full documentation for Animal class.
	</summary>
    </CustomMember>
</CustomDoc>

Tendríamos este resultado:

/// <include file='Docs/AnimalInclude.xml'
/// path='CustomDoc/CustomMember[@name="Animal"]/*'/>

<list>

Permite crear una lista, el elemento <list> admite varios valores bullet/number/table cada uno de los cuales genera la lista en un formato diferente, no numerada, numerada o en formato tabla. Solo si se usa la opción table tiene sentido usar la etiqueta listheader, term y description se pueden considerar como una etiqueta del estilo clave/valor.

/// <summary>
/// It defines a person completely.
/// <list type="table">
/// <listheader>
/// <term>Person</term>
/// <description>Different people.</description>
/// </listheader>
/// <item>
/// <term>Normal.</term>
/// <description>Person from this planet.</description>
/// </item>
/// </list>
/// </summary>

<para>

Se usa dentro de otras etiquetas como <summary> <remarks> <returns>  para agregar estructura al código, como crear párrafos.

/// <summary>
/// Duplicates the name.
/// <para>Generally it is not useful, 
/// but for any person people love it.</para>
/// </summary>

<param>

Sirve para agregar información al parámetro de una función.

/// <param name="secondName">
/// The second name to append.
/// </param>

<paramref>

El nombre de parámetro al que se quiere hacer referencia, es útil para indicar en etiquetas <summary> o <remarks>, por defecto en Sandcastle aparece en cursiva.

/// Clones a person with the 
/// <paramref name="name">supplied
/// </paramref>. 

<typeparam>

Sirve para comentar un tipo genérico o describir un parámetro de tipo. Se agrega una etiqueta para cada parámetro de tipo. El texto se mostrará en IntelliSense, y en Object Browser Window.

/// <typeparam name="T">
/// Type for the array, must be <c>Person</c>
/// </typeparam>

<permission>

Útil para documentar el acceso a un miembro, hay que indicar la clase que gestiona el acceso, para esto se usa habitualmente la clase PermissionSet.

/// <permission cref="System.Security.PermissionSet">
/// Everyone can access this method.
/// </permission

<remarks>

Se usa para agregar información adicional sobre un tipo, proporcionando más  información que la suministrada por <summary>. Esta información se muestra en Object  Browser Window.

/// <remarks> 
/// This is a critical class due to his abstract aspect. 
/// </remarks>

<returns>

Representa el valor devuelto por la función.

/// <returns>
/// Name concatenated itself.
/// </returns>

<see>

Permite especificar un enlace dentro de un texto, el atributo cref permite crear hipervínculos a páginas de documentación.

/// <see 
/// cref="System.Console.WriteLine(System.String)"/>
/// to write to console.

<seealso>

Para indicar el texto que se mostrará en la sección See Also.

/// <summary>
/// Overrides original, 
/// <seealso cref="Person.GetHashCode()"/>.
/// </summary>

<value>

Describe el valor que representa una propiedad.

/// <value>
/// The Address property must not contain extended chars.
/// </value>

Referencias

Recommended Tags for Documentation Comments:
https://msdn.microsoft.com/es-es/library/5ast78ax.aspx
How to: Use the XML Documentation Features (C# Programming Guide)
https://msdn.microsoft.com/es-es/library/z04awywx.aspx

Documentación: Referencia