This is a generator to create a class-diagram of PlantUML from the C# source code.
README.md Version revision history
Version Commit CommentThe class diagram is automatically generated by the Roslyn Source Generator. Details are provided in the link below.
Nuget Gallery: https://www.nuget.org/packages/PlantUmlClassDiagramGenerator
Download and install the .NET 8.0 SDK or newer. Once installed, run the following command.
dotnet tool install --global PlantUmlClassDiagramGenerator
Run the "puml-gen" command.
puml-gen InputPath [OutputPath] [-dir] [-public | -ignore IgnoreAccessibilities] [-excludePaths ExcludePathList] [-createAssociation]
If you omit this option, plantuml files are outputted to same directory as the input files.
Specifies a relative path from the "InputPath", with a comma separated list. To exclude multiple paths, which contain a specific folder name, preceed the name by "**/". Example: "**/bin"
examples
puml-gen C:\Source\App1\ClassA.cs -public
puml-gen C:\Source\App1 C:\PlantUml\App1 -dir -ignore Private,Protected -createAssociation -allInOne
puml-gen C:\Source\App1 C:\PlantUml\App1 -dir -excludePaths bin,obj,Properties
abstract class AbstractClass {
# _x : int
<<internal>> _y : int
# <<internal>> _z : int
+ {abstract} AbstractMethod() : void
# <<virtual>> VirtualMethod(s:string) : void
+ BaseMethod(n:int) : string
class ClassM {
+ {static} <<readonly>> PI : double = 3.141592
+ PropA : int <<get>> <<set>>
+ PropB : int <<get>> <<protected set>>
+ <<event>> SomeEvent : EventHandler
+ <<override>> AbstractMethod() : void
# <<override>> VirtualMethod(s:string) : void
+ <<override>> ToString() : string
+ <<new>> BaseMethod(n:int) : string
AbstractClass <|-- ClassM
Only literal initializers are output.
class ClassC
private int fieldA = 123;
public double Pi {get;} = 3.14159;
protected List<string> Items = new List<string>();
PlantUML
class ClassC {
- fieldA : int = 123
+ Pi : double = 3.14159
# Items : List<string>
Nested classes are expanded and associated with "OuterClass + - InnerClass".
class OuterClass
class InnerClass
struct InnerStruct
PlantUML
class OuterClass{
class InnerClass{
<<struct>> class InnerStruct {
OuterClass +- InnerClass
InnerClass +- InnerStruct
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
If you specify the "createAssociation" option, object associations is created from field and property references.
class ClassA{
public IList<string> Strings{get;} = new List<string>();
public Type1 Prop1{get;set;}
public Type2 field1;
class Type1 {
public int value1{get;set;}
class Type2{
public string string1{get;set;}
public ExternalType Prop2 {get;set;}
PlantUML
@startuml
class ClassA {
class Type1 {
+ value1 : int <<get>> <<set>>
class Type2 {
+ string1 : string <<get>> <<set>>
class "IList`1"<T> {
ClassA o-> "Strings<string>" "IList`1"
ClassA --> "Prop1" Type1
ClassA --> "field1" Type2
Type2 --> "Prop2" ExternalType
@enduml
Record types in C# 9 can have a parameter list. In these cases these parameters
are added as properties to the class.
record Person(string Name, int Age);
record Group(string GroupName) {
public Person[] Members { get; init; }
PlantUML
@startuml
class Person <<record>> {
+ Name : string <<get>> <<init>>
+ Age : int <<get>> <<init>>
class Group <<record>> {
+ GroupName : string <<get>> <<init>>
+ Members : Person[] <<get>> <<init>>
@enduml
You can add the package PlantUmlClassDiagramGenerator.Attributes to your C# project for attribute-based configuration.
Only types to which PlantUmlDiagramAttribute has been added will be output.
This attribute is enabled if the -attributeRequired switch is added to the command line argument.
This attribute can be added only to type declalerations.
class
struct
record
class ClassA
public string Name { get; set; }
public int Age { get; set; }
[PlantUmlDiagram]
class ClassB
public string Name { get; set; }
public int Age { get; set; }
Only ClassB with PlantUmlDiagramAttribute will be output.
@startuml
class ClassB {
+ Name : string <<get>> <<set>>
+ Age : int <<get>> <<set>>
@enduml
Elements with this attribute added are excluded from the output.
[PlantUmlIgnore]
class ClassA
public string Name { get; set; }
public int Age { get; set; }
class ClassB
public string Name { get; set; }
[PlantUmlIgnore]
public int Age { get; set; }
class ClassC
public string Name { get; set; }
public int Age { get; set; }
[PlantUmlIgnore]
public ClassC(string name, int age) => (Name, Age) = (name, age);
public void MethodA();
[PlantUmlIgnore]
public void MethodB();
@startuml
class ClassB {
+ Name : string
class ClassC {
+ Name : string
+ Age : int
+ MethodA() : void
@enduml
By adding this attribute, you can define association between classes.
This attribute can be added to properties, fields and method parameters.
The details of the association are defined in the following properties.
Specifies the type name on the leaf node side.
If omitted, the name of the element to which the attribute is added is used.
Association
Specifies the edge portion of the association.Sets a valid string in PlantUML.
If omitted, "--" is used.
RootLabel
Specifies the label to be displayed on the root node side.
If omitted, nothing is displayed.
Label
Specifies the label to be displayed in the center of the edge.
If omitted, nothing is displayed.
LeafLabel
Specifies the label to be displayed on the leaf node side.
If omitted, nothing is displayed.
class Parameters
public string A { get; set; }
public string B { get; set; }
class CustomAssociationSample
[PlantUmlAssociation(Name = "Name", Association = "*-->", LeafLabel = "LeafLabel", Label= "Label", RootLabel = "RootLabel")]
public ClassA A { get; set; }
class CollectionItemsSample
[PlantUmlAssociation(Name = "Item", Association = "o--", LeafLabel = "0..*", Label = "Items")]
public IList<Item> Items { get; set; }
class MethodParamtersSample
public void Run([PlantUmlAssociation(Association = "..>", Label = "use")] Parameters p)
Console.WriteLine($"{p.A},{p.B}");
private ILogger logger;
public MyClass([PlantUmlAssociation(Association = "..>", Label = "Injection")] ILogger logger)
this.logger = logger;
@startuml
class Parameters {
+ A : string <<get>> <<set>>
+ B : string <<get>> <<set>>
class CustomAssociationSample {
class CollectionItemsSample {
class MethodParamtersSample {
+ Run(p:Parameters) : void
+ MyClass(logger:ILogger)
CustomAssociationSample "RootLabel" *--> "LeafLabel" Name : "Label"
CollectionItemsSample o-- "0..*" Item : "Items"
MethodParamtersSample ..> Parameters : "use"
MethodParamtersSample ..> ILogger : "Injection"
@enduml
This attribute can be added to properties and fields.
Properties (or fields) with this attribute are described as members of the class without any association.
class User
public string Name { get; set; }
public int Age { get; set; }
class ClassA
public static User DefaultUser { get; }
public IList<User> Users { get; }
public ClassA(IList<User> users)
Users = users;
DefaultUser = new User()
Name = "DefaultUser",
Age = "20"
class ClassB
[PlantUmlIgnoreAssociation]
public static User DefaultUser { get; }
[PlantUmlIgnoreAssociation]
public IList<User> Users { get; }
public ClassB(IList<User> users)
Users = users;
DefaultUser = new User()
Name = "DefaultUser",
Age = "20"
@startuml
class User {
+ Name : string <<get>> <<set>>
+ Age : int <<get>> <<set>>
class ClassA {
+ ClassA(users:IList<User>)
class ClassB {
+ {static} DefaultUser : User <<get>>
+ Users : IList<User> <<get>>
+ ClassB(users:IList<User>)
class "IList`1"<T> {
ClassA --> "DefaultUser" User
ClassA --> "Users<User>" "IList`1"
@enduml