当前位置: 首页 > news >正文

【Tools】C#文件自动生成UML图

1. 必要条件:

安装Java环境、安装Graphviz环境:

安装VS Code,在VS Code里安装PlantUML插件、Graphviz Preview插件:

编写convert_cs_to_puml.py文件,将其放在与cs文件放在同一个文件夹:

import os
import redef parse_cs_file(content):"""解析单个C#文件的内容,提取类名、字段、属性、方法、继承关系和依赖。支持静态字段、静态方法、属性、方法参数类型依赖、字段初始化、继承关系。"""class_info = {'name': None,'fields': [],'methods': [],'dependencies': set(),'inherits': None  # 基类}# 提取类名及继承class_match = re.search(r'class\s+([A-Za-z0-9_]+)(\s*:\s*([A-Za-z0-9_<>]+))?', content)if not class_match:return Noneclass_info['name'] = class_match.group(1)if class_match.group(3):class_info['inherits'] = class_match.group(3)class_info['dependencies'].add(class_match.group(3))# 提取字段(支持可选 static 和初始化表达式)field_pattern = re.compile(r'\b(public|private|protected)\s+(static\s+)?([A-Za-z0-9_<>?]+)\s+([A-Za-z0-9_]+)(?:\s*=\s*[^;]+)?\s*;')for match in field_pattern.finditer(content):visibility = match.group(1)is_static = match.group(2)data_type = match.group(3)variable_name = match.group(4)# 添加依赖if data_type not in ['int', 'string', 'bool', 'double', 'float', 'void', 'DateTime']:class_info['dependencies'].add(data_type.replace('?', '').replace('[]', ''))puml_symbol = get_puml_symbol(visibility)field_str = f'  {puml_symbol}{variable_name} : {data_type}'if is_static:field_str = '{static} ' + field_strclass_info['fields'].append(field_str)# 提取属性(Property)property_pattern = re.compile(r'\b(public|private|protected)\s+(static\s+)?([A-Za-z0-9_<>?]+)\s+([A-Za-z0-9_]+)\s*\{\s*get;\s*set;\s*\}')for match in property_pattern.finditer(content):visibility = match.group(1)is_static = match.group(2)data_type = match.group(3)property_name = match.group(4)if data_type not in ['int', 'string', 'bool', 'double', 'float', 'void', 'DateTime']:class_info['dependencies'].add(data_type.replace('?', '').replace('[]', ''))puml_symbol = get_puml_symbol(visibility)prop_str = f'  {puml_symbol}{property_name} : {data_type} {{property}}'if is_static:prop_str = '{static} ' + prop_strclass_info['fields'].append(prop_str)# 提取方法及参数类型(支持 static 和多行参数)method_pattern = re.compile(r'\b(public|private|protected)\s+(static\s+)?([A-Za-z0-9_<>?]+)\s+([A-Za-z0-9_]+)\s*\((.*?)\)\s*{?',re.DOTALL)for match in method_pattern.finditer(content):visibility = match.group(1)is_static = match.group(2)return_type = match.group(3)method_name = match.group(4)params = match.group(5).replace('\n',' ').strip()  # 去掉换行# 返回类型依赖if return_type not in ['int', 'string', 'bool', 'double', 'float', 'void', 'DateTime']:class_info['dependencies'].add(return_type.replace('?', '').replace('[]', ''))# 参数类型依赖if params:param_list = [p.strip() for p in params.split(',')]for p in param_list:parts = p.split()if len(parts) >= 2:param_type = parts[0]if param_type not in ['int', 'string', 'bool', 'double', 'float', 'void', 'DateTime']:class_info['dependencies'].add(param_type.replace('?', '').replace('[]', ''))puml_symbol = get_puml_symbol(visibility)method_str = f'  {puml_symbol}{method_name}({params}) : {return_type}'if is_static:method_str = '{static} ' + method_strclass_info['methods'].append(method_str)return class_infodef get_puml_symbol(visibility):if visibility == 'public':return '+'elif visibility == 'private':return '-'elif visibility == 'protected':return '#'return ''def generate_puml_for_single_class(class_info):if not class_info:return Nonepuml_content = ['@startuml', '', 'skinparam classAttributeIconSize 0']# 类成员puml_content.append(f'class {class_info["name"]} {{')puml_content.extend(class_info['fields'])if class_info['fields'] and class_info['methods']:puml_content.append('')puml_content.extend(class_info['methods'])puml_content.append('}')# 继承关系if class_info['inherits']:puml_content.append(f'{class_info["name"]} --|> {class_info["inherits"]}')puml_content.append('')puml_content.append('@enduml')return '\n'.join(puml_content)def process_and_generate_multiple_files():script_dir = os.path.dirname(os.path.abspath(__file__))found_cs_files = Falsefor filename in os.listdir(script_dir):if filename.endswith('.cs'):found_cs_files = Truefile_path = os.path.join(script_dir, filename)print(f"正在解析文件: {filename}")try:with open(file_path, 'r', encoding='utf-8') as f:content = f.read()class_info = parse_cs_file(content)if class_info:puml_content = generate_puml_for_single_class(class_info)puml_filename = filename.replace('.cs', '.puml')output_file_path = os.path.join(script_dir, puml_filename)with open(output_file_path, 'w', encoding='utf-8') as f:f.write(puml_content)print(f"成功生成 UML 图文件: {puml_filename}")else:print(f"文件 {filename} 中未找到有效的 C# 类定义。")except Exception as e:print(f"解析 {filename} 失败: {e}")if not found_cs_files:print("未找到任何C#文件。")if __name__ == '__main__':process_and_generate_multiple_files()

编写完上面这个文件后,假设现在在同级文件夹下添加一个A.cs,文件内容如下:

public class A
{public int a = 1;
}

运行convert_cs_to_puml.py文件,可以在同级文件夹下看到A.puml:

@startumlskinparam classAttributeIconSize 0
class A {+a : int
}@enduml

最后Alt + D,生成UML图:

http://www.dtcms.com/a/356749.html

相关文章:

  • Vue3 全面介绍
  • ArcGIS Pro 地图打包与解包
  • STM32CubeMX + HAL 库:基于 I²C 通信的 AHT20 高精度温湿度测量实验
  • 佳易王钓场计时计费系统:全方位赋能钓场智能化管理,软件操作教程
  • Halcon那些事:如何使用差异模型create_variation_model检测印刷品缺陷
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(22):文法+单词第7回4 + 考え方1
  • Java全栈开发工程师面试实录:从基础到微服务的深度技术解析
  • LangChain如何使用通义千问的向量模型
  • 嵌入式学习日志————MPU6050简介
  • 2025年社交广告投放技术解析:应对CPM上涨的核心策略与实战方法
  • 元宇宙与娱乐产业:沉浸式体验与内容生态的重构
  • 前端工程化深度实践:从构建优化到CI/CD的完整解决方案
  • 基于无人机的风电叶片全自动智能巡检:高精度停角估计与细节优先曝光调控技术
  • 【Flask】测试平台开发,产品管理实现添加功能-第五篇
  • 【Flask】测试平台开发,集成禅道
  • 【Spring Cloud微服务】6.通信的利刃:深入浅出 Spring Cloud Feign 实战与原理
  • 前端-什么是Vue
  • 如何禁止网站内容被复制:技术、策略与深度思考
  • 【面试系列】谈谈你对数据库ACID的理解
  • 鸿蒙Next导航与路由指南:组件导航与页面路由的完美协作
  • Java中使用Spring Boot+Ollama实现本地AI的MCP接入
  • Dify平台:Agent开发初学者指南
  • Rust:所有权
  • Swift 解法详解:LeetCode 366《寻找二叉树的叶子节点》
  • SOME/IP-SD中”服务器服务组播端点”、“客户端服务组播端点”与“IPv4组播选项的区分
  • 记录:HSD部署(未完成)
  • 如何编译和使用 tomcat-connectors-1.2.32 源码(连接 Apache 和 Tomcat)​附安装包下载
  • CD71.【C++ Dev】二叉树的三种非递归遍历方式
  • 4.渗透-.DOS命令(文件目录操作)
  • 响应式编程框架Reactor【3】