Sdílet prostřednictvím


Generování komentářů dokumentace k rozhraní XML API

Zdrojové soubory jazyka C# můžou obsahovat strukturované komentáře, které vytvářejí dokumentaci k rozhraní API pro typy definované v těchto souborech. Kompilátor jazyka C# vytvoří soubor XML , který obsahuje strukturovaná data představující komentáře a podpisy rozhraní API. Další nástroje mohou zpracovat výstup XML a vytvořit dokumentaci čitelnou pro člověka ve formě webových stránek nebo souborů PDF, například.

Tento proces nabízí celou řadu výhod pro přidání dokumentace k rozhraní API do kódu:

  • Kompilátor jazyka C# kombinuje strukturu kódu jazyka C# s textem komentářů do jednoho dokumentu XML.
  • Kompilátor jazyka C# ověří, že komentáře odpovídají podpisům rozhraní API pro relevantní značky.
  • Nástroje, které zpracovávají soubory dokumentace XML, mohou definovat elementy a atributy XML specifické pro tyto nástroje.

Nástroje, jako je Visual Studio, poskytují IntelliSense pro mnoho běžných elementů XML používaných v komentářích dokumentace.

Tento článek se zabývá těmito tématy:

  • Komentáře dokumentace a generování souborů XML
  • Značky ověřené kompilátorem jazyka C# a sadou Visual Studio
  • Formát vygenerovaného souboru XML

Vytvoření výstupu dokumentace XML

Dokumentaci pro kód vytvoříte napsáním speciálních polí komentářů označených trojitými lomítky. Pole komentáře obsahují elementy XML, které popisují blok kódu, který následuje za komentáři. Například:

/// <summary>
/// This class performs an important function.
/// </summary>
public class MyClass { }

Nastavíte buď možnost GenerateDocumentationFile nebo DocumentationFile , a kompilátor najde všechna pole komentářů se značkami XML ve zdrojovém kódu a vytvoří z těchto komentářů soubor dokumentace XML. Pokud je tato možnost povolená, kompilátor vygeneruje upozornění CS1591 pro všechny veřejně viditelné členy deklarované v projektu bez komentářů dokumentace XML.

Formáty komentářů XML

Použití komentářů dokumentu XML vyžaduje oddělovače, které označují, kde začíná a končí komentář dokumentace. Pomocí následujících oddělovačů se značkami dokumentace XML:

  • /// Jednořádkový oddělovač: Příklady dokumentace a šablony projektů jazyka C# používají tento formulář. Pokud prázdný znak následuje za oddělovačem, není zahrnutý ve výstupu XML.

    Poznámka:

    Visual Studio po zadání /// oddělovače v editoru kódu automaticky vloží <summary> a </summary> umístí kurzor do těchto značek. Tuto funkci můžete zapnout nebo vypnout v dialogovém okně Možnosti.

  • /** */ Víceřádkové oddělovače: Oddělovače /** */ mají následující pravidla formátování:
    • Na řádku, který obsahuje /** oddělovač, pokud je zbytek řádku prázdný, nebude řádek zpracován pro komentáře. Pokud je první znak za /** oddělovačem prázdný znak, bude tento prázdný znak ignorován a zbytek řádku se zpracuje. Jinak se celý text řádku za /** oddělovačem zpracuje jako součást komentáře.

    • Na řádku, který obsahuje */ oddělovač, je-li na oddělovači pouze prázdné znaky */ , bude tento řádek ignorován. V opačném případě se text na řádku až do */ oddělovače zpracuje jako součást komentáře.

    • Pro řádky za řádky, které začínají oddělovačem /** , kompilátor hledá společný vzor na začátku každého řádku. Vzor se může skládat z volitelného prázdného místa nebo hvězdičky (*) a za ní další volitelné prázdné znaky. Pokud kompilátor najde společný vzor na začátku každého řádku, který nezačíná /** oddělovačem nebo končí */ oddělovačem, ignoruje tento vzor pro každý řádek.

    • Jedinou částí následujícího komentáře je řádek, který začíná <summary>. Tři formáty značek vytvářejí stejné komentáře.

      /** <summary>text</summary> */
      
      /**
      <summary>text</summary>
      */
      
      /**
      * <summary>text</summary>
      */
      
    • Kompilátor identifikuje běžný vzor " * " na začátku druhého a třetího řádku. Vzor není součástí výstupu.

      /**
      * <summary>
      * text </summary>*/
      
    • Kompilátor nenajde v následujícím komentáři žádný běžný vzor, protože druhý znak na třetím řádku není hvězdička. Veškerý text na druhém a třetím řádku se zpracuje jako součást komentáře.

      /**
      * <summary>
         text </summary>
      */
      
    • Kompilátor nenajde v následujícím komentáři žádný vzor ze dvou důvodů. Za prvé, počet mezer před hvězdičkou není konzistentní. Za druhé, pátý řádek začíná tabulátorem, který neodpovídá mezery. Veškerý text z řádků dvou až pěti se zpracuje jako součást komentáře.

      /**
        * <summary>
        * text
      *  text2
       	*  </summary>
      */
      

Pokud chcete odkazovat na elementy XML (například funkce zpracovává specifické elementy XML, které chcete popsat v komentáři dokumentace XML), můžete použít standardní mechanismus uvozování (&lt; a &gt;). Pokud chcete odkazovat na obecné identifikátory v elementech odkazu na kód (cref), můžete použít řídicí znaky (například cref="List&lt;T&gt;") nebo složené závorky (cref="List{T}"). Ve speciálním případě kompilátor parsuje složené závorky jako úhlové závorky, aby komentář k dokumentaci byl pro autora při odkazování na obecné identifikátory méně těžkopádný.

Poznámka:

Pokud píšete komentáře pomocí oddělovače komentářů XML s jedním řádkem, ///ale neobsahuje žádné značky, kompilátor přidá text těchto komentářů do výstupního souboru XML. Výstup ale neobsahuje elementy XML, například <summary>. Většina nástrojů, které využívají komentáře XML (včetně technologie Visual Studio IntelliSense), tyto komentáře nečte.

Nástroje, které přijímají vstup dokumentace XML

Následující nástroje vytvářejí výstup z komentářů XML:

  • DocFX: DocFX je generátor dokumentace rozhraní API pro .NET, který aktuálně podporuje C#, Visual Basic a F#. Umožňuje také přizpůsobit vygenerovanou referenční dokumentaci. DocFX vytvoří statický web HTML ze zdrojového kódu a souborů Markdownu. DocFX vám také poskytuje flexibilitu při přizpůsobení rozložení a stylu webu prostřednictvím šablon. Můžete také vytvořit vlastní šablony.
  • Sandcastle: Nástroje Sandcastle vytvářejí soubory nápovědy pro knihovny spravovaných tříd obsahující koncepční i referenční stránky rozhraní API. Nástroje Sandcastle jsou založené na příkazovém řádku a nemají žádné front-endové grafické uživatelské rozhraní, funkce řízení projektů ani automatizovaný proces sestavení. Tvůrce souborů nápovědy Sandcastle poskytuje samostatné grafické uživatelské rozhraní a nástroje založené na příkazovém řádku pro automatické sestavení souboru nápovědy. K dispozici je také integrační balíček sady Visual Studio, aby bylo možné vytvářet a spravovat projekty nápovědy zcela ze sady Visual Studio.
  • Doxygen: Doxygen generuje online prohlížeč dokumentace (v HTML) nebo offline referenční příručku (v LaTeX) ze sady dokumentovaných zdrojových souborů. K dispozici je také podpora generování výstupu ve formátu RTF (MS Word), PostScriptu, hypertextovém odkazu PDF, komprimovaném HTML, DocBooku a Unixu. Doxygen můžete nakonfigurovat tak, aby extrahovali strukturu kódu z nezdokumentovaných zdrojových souborů.

Poznámka:

Komentáře dokumentace XML nejsou metadata; nejsou zahrnuty do kompilovaného sestavení, a proto nejsou přístupné prostřednictvím reflexe.

Řetězce ID

Každý typ nebo člen je uložen v elementu ve výstupním souboru XML. Každý z těchto prvků má jedinečný řetězec ID, který identifikuje typ nebo člen. Řetězec ID musí odpovídat operátorům, parametrům, návratovým hodnotám, parametrům obecného typu, ref, ina out parametrům. Aby bylo možné zakódovat všechny tyto potenciální prvky, kompilátor dodržuje jasně definovaná pravidla pro generování řetězců ID. Programy, které zpracovávají soubor XML, používají řetězec ID k identifikaci odpovídajících metadat rozhraní .NET nebo položky reflexe, na které se dokumentace vztahuje.

Kompilátor při generování řetězců ID dodržuje následující pravidla:

  • V řetězci není žádné prázdné znaky.

  • První část řetězce identifikuje druh členu pomocí jednoho znaku následovaného dvojtečka. Používají se následující typy členů:

    Znak Typ členu Poznámky
    N názvový prostor Do oboru názvů nemůžete přidávat komentáře dokumentace, ale tam, kde je to podporované, můžete na ně odkazovat cref .
    T typ Typ je třída, rozhraní, struktura, výčet nebo delegát.
    F pole
    P vlastnost Zahrnuje indexery nebo jiné indexované vlastnosti.
    M metoda Zahrnuje speciální metody, jako jsou konstruktory a operátory.
    E událost
    ! text chyby Zbytek řetězce poskytuje informace o chybě. Kompilátor jazyka C# vygeneruje informace o chybě pro odkazy, které nelze vyřešit.
  • Druhá část řetězce je plně kvalifikovaný název položky počínaje kořenem oboru názvů. Název položky, její nadřazené typy a obor názvů jsou oddělené tečkami. Pokud název položky obsahuje tečky, nahradí se znakem hash (#). Gramatika předpokládá, že žádná položka nemá ve svém názvu přímo znak hash. Například plně kvalifikovaný název konstruktoru String je "System.String.#ctor".

  • Pro vlastnosti a metody následuje seznam parametrů uzavřený v závorkách. Pokud neexistují žádné parametry, nejsou k dispozici žádné závorky. Parametry jsou oddělené čárkami. Kódování každého parametru přímo sleduje, jak je kódován v podpisu .NET (viz Microsoft.VisualStudio.CorDebugInterop.CorElementType definice všech prvků caps v následujícím seznamu):

    • Základní typy. Běžné typy (ELEMENT_TYPE_CLASS nebo ELEMENT_TYPE_VALUETYPE) jsou reprezentovány jako plně kvalifikovaný název typu.
    • Vnitřní typy (například ELEMENT_TYPE_I4, , ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_STRINGELEMENT_TYPE_TYPEDBYREF, a ELEMENT_TYPE_VOID) jsou reprezentovány jako plně kvalifikovaný název odpovídajícího úplného typu. Například System.Int32 nebo System.TypedReference.
    • ELEMENT_TYPE_PTR je reprezentována jako *za upraveným typem.
    • ELEMENT_TYPE_BYREF je reprezentován jako znak @za upraveným typem.
    • ELEMENT_TYPE_CMOD_OPT je reprezentována jako "!" a plně kvalifikovaný název modifikační třídy, za upraveným typem.
    • ELEMENT_TYPE_SZARRAY je reprezentován jako "[]" za typem prvku pole.
    • ELEMENT_TYPE_ARRAY je reprezentován jako [dolní mez:size,dolní mez:size] kde počet čárek je pořadí - 1 a dolní mez a velikost každé dimenze, pokud je známo, jsou reprezentovány v desítkové soustavě. Dolní mez a velikost jsou vynechány, pokud nejsou zadány. Pokud je vynechána dolní mez a velikost konkrétní dimenze, vynechá se také hodnota :. Například dvojrozměrné pole s hodnotou 1 jako dolní mez a nezadaná velikost je [1:,1:].
  • Pouze pro převodní operátory (op_Implicit a op_Explicit), návratová hodnota metody je kódována jako ~ následovaný návratový typ. Například: <member name="M:System.Decimal.op_Explicit(System.Decimal arg)~System.Int32"> je značka operátoru přetypování public static explicit operator int (decimal value); deklarovaného ve System.Decimal třídě.

  • U obecných typů je název typu následovaný zpětným znaménkam a číslem, které označuje počet parametrů obecného typu. Příklad: <member name="T:SampleClass`2"> je značka pro typ, který je definován jako public class SampleClass<T, U>. U metod, které jako parametry přebírají obecné typy, jsou parametry obecného typu zadány jako čísla před uvedenými backticky (například 0,1). Každé číslo představuje zápis pole založené na nule pro obecné parametry typu.

    • ELEMENT_TYPE_PINNED je reprezentován jako ^za změněným typem. Kompilátor jazyka C# toto kódování nikdy negeneruje.
    • ELEMENT_TYPE_CMOD_REQ je reprezentována jako | a plně kvalifikovaný název modifikační třídy za upraveným typem. Kompilátor jazyka C# toto kódování nikdy negeneruje.
    • ELEMENT_TYPE_GENERICARRAY je reprezentován jako "[?]" za typem prvku pole. Kompilátor jazyka C# toto kódování nikdy negeneruje.
    • ELEMENT_TYPE_FNPTR je reprezentována jako "=FUNC:type(signature)", kde type je návratový typ a podpis je argumenty metody. Pokud neexistují žádné argumenty, vynechá se závorky. Kompilátor jazyka C# toto kódování nikdy negeneruje.
    • Následující komponenty podpisu nejsou reprezentovány, protože se nepoužívají k rozlišení přetížených metod:
      • konvence volání
      • návratový typ
      • ELEMENT_TYPE_SENTINEL

Následující příklady ukazují, jak se generují řetězce ID pro třídu a její členy:

namespace MyNamespace;

/// <summary>
/// Enter description here for class X.
/// ID string generated is "T:MyNamespace.MyClass".
/// </summary>
public unsafe class MyClass
{
    /// <summary>
    /// Enter description here for the first constructor.
    /// ID string generated is "M:MyNamespace.MyClass.#ctor".
    /// </summary>
    public MyClass() { }

    /// <summary>
    /// Enter description here for the second constructor.
    /// ID string generated is "M:MyNamespace.MyClass.#ctor(System.Int32)".
    /// </summary>
    /// <param name="i">Describe parameter.</param>
    public MyClass(int i) { }

    /// <summary>
    /// Enter description here for field Message.
    /// ID string generated is "F:MyNamespace.MyClass.Message".
    /// </summary>
    public string? Message;

    /// <summary>
    /// Enter description for constant PI.
    /// ID string generated is "F:MyNamespace.MyClass.PI".
    /// </summary>
    public const double PI = 3.14;

    /// <summary>
    /// Enter description for method Func.
    /// ID string generated is "M:MyNamespace.MyClass.Func".
    /// </summary>
    /// <returns>Describe return value.</returns>
    public int Func() => 1;

    /// <summary>
    /// Enter description for method SomeMethod.
    /// ID string generated is "M:MyNamespace.MyClass.SomeMethod(System.String,System.Int32@,System.Void*)".
    /// </summary>
    /// <param name="str">Describe parameter.</param>
    /// <param name="num">Describe parameter.</param>
    /// <param name="ptr">Describe parameter.</param>
    /// <returns>Describe return value.</returns>
    public int SomeMethod(string str, ref int num, void* ptr) { return 1; }

    /// <summary>
    /// Enter description for method AnotherMethod.
    /// ID string generated is "M:MyNamespace.MyClass.AnotherMethod(System.Int16[],System.Int32[0:,0:])".
    /// </summary>
    /// <param name="array1">Describe parameter.</param>
    /// <param name="array">Describe parameter.</param>
    /// <returns>Describe return value.</returns>
    public int AnotherMethod(short[] array1, int[,] array) { return 0; }

    /// <summary>
    /// Enter description for operator.
    /// ID string generated is "M:MyNamespace.MyClass.op_Addition(MyNamespace.MyClass,MyNamespace.MyClass)".
    /// </summary>
    /// <param name="first">Describe parameter.</param>
    /// <param name="second">Describe parameter.</param>
    /// <returns>Describe return value.</returns>
    public static MyClass operator +(MyClass first, MyClass second) { return first; }

    /// <summary>
    /// Enter description for property.
    /// ID string generated is "P:MyNamespace.MyClass.Prop".
    /// </summary>
    public int Prop { get { return 1; } set { } }

    /// <summary>
    /// Enter description for event.
    /// ID string generated is "E:MyNamespace.MyClass.OnHappened".
    /// </summary>
    public event Del? OnHappened;

    /// <summary>
    /// Enter description for index.
    /// ID string generated is "P:MyNamespace.MyClass.Item(System.String)".
    /// </summary>
    /// <param name="str">Describe parameter.</param>
    /// <returns></returns>
    public int this[string s] => 1;

    /// <summary>
    /// Enter description for class Nested.
    /// ID string generated is "T:MyNamespace.MyClass.Nested".
    /// </summary>
    public class Nested { }

    /// <summary>
    /// Enter description for delegate.
    /// ID string generated is "T:MyNamespace.MyClass.Del".
    /// </summary>
    /// <param name="i">Describe parameter.</param>
    public delegate void Del(int i);

    /// <summary>
    /// Enter description for operator.
    /// ID string generated is "M:MyNamespace.MyClass.op_Explicit(MyNamespace.MyClass)~System.Int32".
    /// </summary>
    /// <param name="myParameter">Describe parameter.</param>
    /// <returns>Describe return value.</returns>
    public static explicit operator int(MyClass myParameter) => 1;
}

Specifikace jazyka C#

Další informace najdete v příloze specifikace jazyka C# v komentářích dokumentace.