当前位置: 首页 > 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.xdnf.cn/news/1388179.html

相关文章:

  • Java流程控制03——顺序结构(本文为个人学习笔记,内容整理自哔哩哔哩UP主【遇见狂神说】的公开课程。 > 所有知识点归属原作者,仅作非商业用途分享)
  • “设计深圳”亚洲权威消费科技与室内设计盛会
  • Nginx高级配置 | Nginx变量使用
  • RoadMP3告别车载音乐烦恼,一键get兼容音频
  • 20250828在荣品RD-RK3588-MID开发板的Android13系统下适配Bainianxing的GPS模块BU-16M10
  • STM32项目分享:基于单片机的自行车测速系统设计
  • C++ DDS框架学习
  • 【前端教程】用 JavaScript 实现4个常用时间与颜色交互功能
  • mysql安全运维之常见攻击类型与防御指南-从SQL注入到权限提升
  • iOS 文件管理与 uni-app 性能优化实战 多工具协作的完整指南
  • 知识卡片html5动态网页源码
  • 2025-08-28-zabbix5.0创建监控项通过脚本简单实现监控oracle11g的磁盘组和表空间的使用量
  • 【从零开始搭建你的 AI 编程助手知识库】
  • Docker的常用命令及简单使用
  • 微积分 | 积分代换
  • 探索永洪vividime的超链接功能:数据分析的桥梁
  • C# NET5.0及以上版本中如何处理MySQL大数据查询
  • 数据防泄与最小可见:ABP 统一封装行级安全(RLS)+ 列级脱敏
  • Go对接全球期货数据源指南:基于StockTV API实现多品种实时监控
  • whisper-large-v3 模型
  • Rust Tokio异步任务实战教程(高级功能)
  • 【前端教程】二维数组排序实战:按需封装才是最优解——拒绝冗余,精简代码
  • Rust语言能干什么
  • PHP的uniqid() 函数分析
  • LangChain实战(二):环境搭建与Hello World(国内开源模型版)
  • 嵌入式Linux驱动开发 - 并发控制机制
  • 【开题答辩全过程】以 基于Spring Boot的网上家庭烹饪学习系统的设计与实现为例,包含答辩的问题和答案
  • 不止 ChatGPT:多模态 AI(文本 + 图像 + 音频)正重构内容创作全流程
  • 以技术赋能强化消费者信任,助推餐饮服务质量提质增效的明厨亮灶开源了
  • [密码学实战]基于SM2实现协同签名(四十五)