如何在 DocFX 中添加 .NET 命名空间信息

How can I add .NET namespace information in DocFX

标题说明了一切...

在 Sandcastle Help File Builder 中,我们将 NamespaceDoc class 添加到每个命名空间以创建命名空间文档。

我们如何使用 DocFX 来实现同样的效果?

无法直接在源代码中添加它。您可以使用 overwrite files 添加命名空间类型的摘要。

这是我的做法:

  1. 在文档项目的根文件夹中,添加一个名为 namespaces.
  2. 的文件夹
  3. 更新您的 docfx.json 文件以包含添加到 namespaces 文件夹的标记文件。您需要在 build 部分更新 overwrite 属性。它看起来像这样:
    "overwrite": [
      {
        "files": [
          "apidoc/**.md",
          "namespaces/**.md"
        ],
        "exclude": [
          "obj/**",
          "_site/**"
        ]
      }
    ],
  1. namespaces 文件夹中为每个要添加文档的命名空间创建一个 markdown 文件。最好将这些文件命名为与名称空间相同的名称。

    这些文件应该有一个 YAML header,其 UID 与命名空间的名称相匹配。 summary: *content 行告诉 docfx overwrite 使用此文件内容的命名空间摘要。

    页面的其余部分是标准降价,将成为命名空间的摘要。例如:

    ---
    uid: My.Groovy.Namespace
    summary: *content
    ---
    The My.Groovy.Namespace namespace contains a bunch of classes and interfaces.

我可能对这个问题已经很晚了,但我遇到了类似的问题,我发现的解决方案包括从源代码修改 docfx 并添加帮助 classes,很像 Sandcastle 的解决方案。

Disclamer:

I do not claim that the solution i'm showcasing is programmatically stable, safe or even correct. I do not claim that this solution will work in any scenario or for any use. I only verify that, for me, it worked perfectly fine, even though i recongize it's just a fast-put-up workaround.

步骤:

  1. 我从他们的 github 的 releases 页面(2.59.2,截至今天)下载了 docfx 的源代码

  1. 解压后,我打开文件docfx-2.59.2\src\Microsoft.DocAsCode.Metadata.ManagedReference\ExtractMetadataWorker.cs

  1. 在此文件中实现的 class 包含一个名为 GetMetadataFromProjectLevelCache 的方法,该方法在某些时候提取元数据 从引用的项目中以树的形式。
private Tuple<MetadataItem, bool> GetMetadataFromProjectLevelCache(IBuildController controller, IInputParameters key){
   // [...]
   projectMetadata = controller.ExtractMetadata(key); // THIS line
   // [...]
}

  1. 在这一行之后,我附加了以下包含我也必须实现的方法的行。
private Tuple<MetadataItem, bool> GetMetadataFromProjectLevelCache(IBuildController controller, IInputParameters key){
   // [...]
   projectMetadata = controller.ExtractMetadata(key);
   ExtractNamespaceDocumentation(projectMetadata); // THIS line
   // [...]
}

  1. 实施如下:
private void ExtractNamespaceDocumentation(MetadataItem node)
{
    // Terminal nodes are not of our interest in any case
    // Even if it's a namespace, it does not contain documentation
    if (node.Items is not { Count: > 0 }) return;
    
    // If it is namespace
    if (node.Type == MemberType.Namespace)
    {
        // Get (if any), the child that is class and is named "_NamespaceDoc"
        var doc = node.Items.FirstOrDefault(x =>
            x.Type == MemberType.Class && x.Name.Split('.').Last() == "_NamespaceDoc");

        // If we didn't found such class, the namespace does not contain documentation.
        // Leave and don't go further.
        if (doc is null) return;

        // Else, assign the class' Summary and remarks to the Namespace and remove the class from the tree.
        node.Summary = doc.Summary;
        node.Remarks = doc.Remarks;
        node.Items.Remove(doc);

        // job finished for this namespace, we do not want to go further down the tree.
        return;
    }

    // For non-namespace intermediate nodes (IE assembly nodes), visit the children.
    foreach (var child in node.Items) ExtractNamespaceDocumentation(child);
}

  1. 最后,我编译了解决方案,通过使用位于 docfx-2.59.2\src\docfx\bin\Debug\net472 的新创建的 docfx.exe,我能够检测到所有名为 _NamespaceDoc 的 class 和使用他们的 <summary> 标签来填充他们所在的命名空间。

为了记录,我决定在我的项目的根目录下创建一个新的 .cs 文件以包含所有 _NamespaceDoc classes,这样我会更容易当我想发布项目时禁用整个文件。该文件如下所示:

namespace RootNamespace
{
    /// <summary>
    /// Documentation for the Root Namespace
    /// </summary>
    public static class _NamespaceDoc { }
}

namespace RootNamespace.SubFolder
{
    /// <summary>
    /// Documentation for the Root Namespace's `SubFolder` Sub-Namespace.
    /// </summary>
    public static class _NamespaceDoc { }
}

// [...]

希望这可以帮助寻求此类解决方案的其他伙伴,甚至 docfx 开发人员和贡献者更可靠地实现此功能。


更新:

有关此方法的更多信息,我已经开始 discussion 在 docfx 的 github 存储库