このドキュメントの内容
Sandcastle を使わずにクラスリファレンスを出力するライブラリ mxProject.Tools.ClassDoc
を作成しました。
特徴を簡単に説明します。GitHub の Readme とほぼ同じ内容です。
公開先
- GitHub
- Nuget
機能
XMLコメントファイルの読み込み
VisualStudio から出力される XML コメントファイルを読み込み、リフレクションで取得された型やメンバの情報に関連付けます。次のタグをサポートしています。
- summary
- param
- returns
- paramref
- typeparamref
- exception
- remarks
inheritdoc タグ
<inheritdoc> タグによるコメントの継承をサポートしています。
次の例では、SubClass.OutputDodument のメソッドから BaseClass.OutputDodument メソッドに記述されたコメントの内容を参照できます。
public class BaseClass
{
/// <summary>
/// Output to document.
/// </summary>
public virtual void OutputDocument() {}
}
public class SubClass : BaseClass
{
/// <inheritdoc/>
public override void OutputDocument() {}
}
参照タグの置き換え
<see>, <seealso>, <paramref>, <typeparamref> タグをリンク文字列などに置き換えることができます。
次のような see タグがソースコードの XML コメント内に記述されているとします。
<see cref="SampleClass"/>
<see cref="SampleClass.SampleMethod"/>
XML コメントファイルには次のように出力されます。cref には型やメンバを表す識別子が出力されます。
<see cref="T:SampleNamespace.SampleClass"/>
<see cref="M:SampleNamespace.SampleClass.SampleMethod"/>
IClassDocumentFormatter
インターフェースの実装により、次のような文字列に置き換えて出力することができます。
[SampleClass](./SampleNamespace/SampleClass.md)
[SampleClass.SampleMethod](./SampleNamespace/SampleClass.md#SampleMethod)
※ 異なるページ内のアンカーへ直接遷移することは実現できていません。上の例では "#SampleMethod" アンカーには遷移せず、"SampleClass.md" ページの先頭へ遷移します。
ドキュメントへの出力
ドキュメント出力は主に IClassDocumentWriter インターフェースと IClassDocumentFormatter インターフェースの機能を利用します。
ライブラリには次の実装を含んでいます。上記のリンク先のページもこれらのクラスを用いて出力したものです。
- RazorEngine を使用してファイルに出力する RazorDocumentWriter クラス
- Markdown 形式のリンクやアンカーへの文字列フォーマットを行う MarkdownFormatter クラス
使用方法
次の例では、LoadAssemblies フォルダに格納されたアセンブリとXMLコメントファイルを読み込み、クラスリファレンスを出力しています。使用しているテンプレートと出力結果は公開先を参照してください。
-
テンプレート
-
出力ファイル
static void OutputDocument()
{
// Razor テンプレート
string typeTemplate = @".\RazorTemplates\TypeTemplate.txt";
string namespaceTemplate = @".\RazorTemplates\NamespaceTemplate.txt";
// 読み込むアセンブリ
string[] dlls = new[]
{
@".\LoadAssemblies\mxProject.Tools.ClassDoc.dll",
@".\LoadAssemblies\mxProject.Tools.ClassDoc.Razor.dll",
@".\LoadAssemblies\SampleLibrary1.dll",
@".\LoadAssemblies\SampleLibrary2.dll"
};
// ライターを設定(.NET Framework バージョンの場合)
RazorDocumentWriter writer = new RazorDocumentWriter(Encoding.UTF8)
{
RootDirectory = @".\Documents\",
TypeDocumentTemplate = File.ReadAllText(typeTemplate, Encoding.UTF8),
NamespaceDocumentTemplate = File.ReadAllText(namespaceTemplate, Encoding.UTF8),
};
// ライターを設定(.NET Core バージョンの場合)
string typeDocTemplate = File.ReadAllText(typeTemplate, Encoding.UTF8);
string namespaceDocTemplate = File.ReadAllText(namespaceTemplate, Encoding.UTF8);
using RazorDocumentWriter writer = RazorDocumentWriter.Create
(
Encoding.UTF8,
namespaceDocTemplate,
typeDocTemplate
);
weiter.RootDirectory = @".\Documents\";
// コンテキストとフォーマッターを設定
ClassDocContext context = new ClassDocContext()
{
// 出力対象を決定するフィルタメソッド
// ここで設定している値は ClassDocContext の初期値として設定されているものと同じです
ConstructorFilter = ConstructorInfoExtensions.IsRecommendOutputToDocument,
TypeFilter = TypeExtenstions.IsRecommendOutputToDocument,
PropertyFilter = PropertyInfoExtensions.IsRecommendOutputToDocument,
FieldFilter = FieldInfoExtensions.IsRecommendOutputToDocument,
MethodFilter = MethodInfoExtensions.IsRecommendOutputToDocument,
EventFilter = EventInfoExtensions.IsRecommendOutputToDocument,
};
MarkdownFormatter formatter = new MarkdownFormatter(context)
{
// アンカーのフォーマット
// ここで設定している値は MarkdownFormatter の初期値として設定されているものと同じです
ConstructorAnchorDefaultFormat = "{0} Constructor",
PropertyAnchorDefaultFormat = "{0} Property",
FieldAnchorDefaultFormat = "{0} Field",
MethodAnchorDefaultFormat = "{0} Method",
EventAnchorDefaultFormat = "{0} Event",
ParameterNameDefaultFormat = "`{0}`",
};
// 型情報を読み込みます
IReadOnlyList<TypeWithComment> types = TypeLoader.LoadTypes(dlls, context, null);
// 名前空間ごとにグループ化します
foreach (var group in types.GroupBy(type => type.Namespace).OrderBy(group => group.Key))
{
NamespaceInfo nameSpace = new NamespaceInfo(group.First()?.Namespace, group);
// 名前空間の情報をドキュメントに出力します
writer.WriteNamespaceDocument(nameSpace, formatter);
// 型の情報をドキュメントに出力します
foreach (var type in group.OrderBy(type => type.Name))
{
writer.WriteTypeDocument(type, formatter);
}
}
}
最後に
こういったライブラリの拡充が XML コメントを記述するモチベーションにつながれば幸いです。