C#のソースコードからPlantUMLのクラス図を生成するアプリ(改)をリリースしました
サンプルコードの棚卸
以前、以下の記事で作成したC#ソースコードからPlantUMLを生成するサンプルプログラムですが、(長らく放置状態でしたが)
少し手直しをして、それなりに使えるようにしました。
PlantUmlClassDiagramGenerator
リポジトリはこちら
こちらからバイナリ(.zip)をダウンロードできます。ぜひお試しください。
使い方
PlantUmlClassDiagramGeneratorはコンソールアプリケーションです。 以下の様にパラメータを指定して実行します。
C:\> PlantUmlClassDiagramGenerator.exe InputPath [OutputPath] [-dir] ^ [-public | -ignore IgnoreAccessibilities] [-excludePaths ExcludePathList]
- InputPath (必須)
入力するソースコードのファイル名またはディレクトリ名を指定します。
ディレクトリを指定した場合、サブフォルダ以下を含めた全ての.cs
ファイルが変換の対象となります。 - OutputPath (省略可)
出力先のファイル名またはディレクトリ名を指定します。
省略した場合、変換元の.cs
ファイルと同じディレクトリに変換後の.puml
ファイルが出力されます。 - -dir (省略可)
InputPath および OutputPath がディレクトリ名の場合にこのオプションを指定します。 - -public (省略可)
クラス、構造体のパブリックメンバーのみを出力する場合に指定します。 - -ignore (省略可)
出力対象外とするアクセシビリティをカンマ区切りで指定します。
(例):-ignore private,protected
- -excludePaths (省略可)
除外するファイル名またはディレクトリ名を指定します。-dir オプションを指定した場合のみ有効
(例):-excludePaths obj,Properties\AssemblyInfo.cs
使用例
例として、こちらのソースコードを変換してみます。
ソリューションディレクトリをC:\Source\CsvEditSharp
として、プロジェクトCsvEditSharp以下の.cs
ファイルをまとめて変換する場合を例にします。
出力先はC:\Source\CsvEditSharp\Documents\uml
とします。
C:\> PlantUmlClassDiagramGenerator.exe C:\Source\CsvEditSharp\CsvEditSharp ^ C:\Source\CsvEditSharp\Documents\uml -dir -public -excludePaths obj,Properties
今回は、パブリックメンバーのみを出力対象としました。
また、obj
フォルダ内に自動生成される.cs
ファイルと、Properties
フォルダ内のAssemblyInfo.cs
ファイルは変換対象から除外するようにしました。
変換結果は以下で確認できます。
CsvEditSharp/Documents/uml at master · pierre3/CsvEditSharp · GitHub
ちなみに、ディレクトリ単位で変換を行った場合、全ての出力ファイルを !include
で参照したinclude.puml
をInputPath内に出力するようにしています。
@startuml !include .\\App.xaml.puml !include .\\Models\ColumnValidation.puml !include .\\Models\CompletionData.puml !include .\\Models\CsvConfigFileManager.puml !include .\\Models\CsvEditSharpConfigurationHost.puml !include .\\Models\CsvEditSharpWorkspace.puml !include .\\Models\CustomBooleanConverter.puml !include .\\Models\EnumerableExt.puml !include .\\Models\GenerateConfigSettings.puml !include .\\Models\ICsvEditSharpConfigurationHost.puml !include .\\Models\RegisterClassMapTarget.puml !include .\\Models\SaveConfigSettings.puml //...(中略)... !include .\\ViewModels\GenerateConfigDialogViewModel.puml !include .\\ViewModels\MainWindowViewModel.puml !include .\\ViewModels\SaveConfigDialogViewModel.puml !include .\\Views\GenerateConfigDialog.xaml.puml !include .\\Views\MainWindow.xaml.puml !include .\\Views\SaveConfigDialog.xaml.puml @enduml
これをそのままPlantUMLで画像に変換すると、こんな感じになります↓
http://pierre3net.azurewebsites.net/content/image/include.svg
主な変更点
以前の記事に書いた仕様からの主な変更点は以下の通りです。
ネストクラスの扱い
ネストされたクラスは、ネストのまま変換されてPlantUMLでエラーとなってしまっていましたが、
今回、ネストクラスは外に展開して、+--
で関連付けするように修正しました。
class OuterClass { class InnerClass { struct InnerStruct { } }
- PlantUML
class OuterClass{ } class InnerClass{ } <<struct>> class InnerStruct { } OuterClass +- InnerClass InnerClass +- InnerStruct
ジェネリクス型の変換
PlantUMLでは、ジェネリクス型は型引数の数が異なっても同じクラスとして認識されてしまうようです。
class GenericsType { } class GenericsType<T1> { } class GenericsType<T1,T2> { }
PlantUMLでは、上記は全て GenericsType
クラスとして認識され、ダイアグラムは最後に記述した定義で上書きされてしまいます。
そこで今回は、以下の様に"クラス名に型引数の数を付加したもの"を変換後のクラス名とするようにしました。
class "GenericsType`1"<T1>{ } class "GenericsType`2"<T1,T2>{ }
継承関係
クラス、インターフェースを継承しているクラスは、ベースクラスと<|--
で結んで継承関係を表すようにしました。
abstract class BaseClass { public abstract void AbstractMethod(); protected virtual int VirtualMethod(string s) => 0; } class SubClass : BaseClass { public override void AbstractMethod() { } protected override int VirtualMethod(string s) => 1; } interface IInterfaceA {} interface IInterfaceA<T>:IInterfaceA { T Value { get; } } class ImplementClass : IInterfaceA<int> { public int Value { get; } }
- PlantUML
abstract class BaseClass { + {abstract} AbstractMethod() : void # <<virtual>> VirtualMethod(s:string) : int } class SubClass { + <<override>> AbstractMethod() : void # <<override>> VirtualMethod(s:string) : int } interface IInterfaceA { } interface "IInterfaceA`1"<T> { Value : T <<get>> } class ImplementClass { + Value : int <<get>> } BaseClass <|-- SubClass IInterfaceA <|-- "IInterfaceA`1" "IInterfaceA`1" "<int>" <|-- ImplementClass